home *** CD-ROM | disk | FTP | other *** search
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create:
- # HELP
- # Makefile
- # README
- # bitmatrix.c
- # bitmatrix.h
- # corridors.c
- # corridors.h
- # domino.c
- # domino.h
- # externs.h
- # games.c
- # grammar.y
- # hash.c
- # hash.h
- # list.c
- # list.h
- # main.c
- # operations.c
- # operations.h
- # output.c
- # output.h
- # parse.l
- # rational.c
- # rational.h
- # This archive created: Sun Oct 6 20:23:54 1991
- export PATH; PATH=/bin:/usr/bin:$PATH
- if test -f 'HELP'
- then
- echo shar: "will not over-write existing file 'HELP'"
- else
- cat << \SHAR_EOF > 'HELP'
- Run without arguments, the games program executes each argument as
- a command line, and then exits. For instance, typing
- games evaluate tex "2||1|*"
- will output
- 1 \int{ 1\over 4}
-
- Things enclosed in []'s are subscripts and things in <>'s are superscripts.
- ---------------------------------------------------------
- 7/2 G -> Q | N numbers | N integer
- ^3 G -> ^N | ^ up (v is down) | G game
- *5 G -> *N | * star | L list
- +[2] G -> +[G] tiny (- is miny) | Q rational
- | V variable
- {^3} G -> {G} | (G) (same for L's) --------------
- 3||2|1 G -> L '|' L 3 vs (2 vs 1)
- 3,{4|2}|1 L -> G | G,L {3,{4|2}}|1
-
- 3+2 G -> G + G | G - G add/subtract
- (3|2)[1/4] G -> G[Q] cool G by Q
- (3|2)[] G -> G[] apply chill-function to G
- mean (3|2) Q -> mean G mean
- temperature (3|2) Q -> temperature G temperature
- freeeze (3|2) G -> freeze G cool by temperature
- %[1*]<1>(3|2) G -> %[G]<G>G overheating
- %(3|2) G -> %G apply warm-function to G
- +[3]<3> G -> G<N> generalization of up^n
- [+[3]]<(3)> G -> on G <N> generalization of upon
- 0<3>|+[3] G -> 0<n> '|' G 0|||0||0|G
- ^3.1* G -> G.G Norton multiply
- aw (0|+[1]) G -> aw G atomic weight
- 1 ? * -> G ? G compare games (<, >, =, or <>)
-
- x G -> G get variable's value
- vAr7=2 G -> V=G set variable
- V -> [a-zA-Z]+[0-9]* variable starts with character
-
- corridor (1u2(b3)) G -> corridor... invading corridors in go
- domino G -> domino <cr> ... evaluate a domineering position
- chill g[1] -> chill f(g) set chilling function (for evaluate)
- warm g.1* -> warm f(g) set warming funcion (for evaluate)
- K G -> "K" | "k" K = 1 point ko, k = chilled K
-
- -- PRINT OPTIONS --
- no (option) Cancel option
- integers Recognize canonical forms of integers
- numbers
- stars
- ups
- tinys
- ons
- variables Substitute variable names for games
- expand If outputing a game identical to a variable, give both
- prompt Give prompt of "> "
- all All of the above options are set
- evaluate Tries to chill and warm back up
- normalize With evaluate, normalizes the result to n%g (default's to on)
- assume Make unproven assumptions about go positions for efficiency
- assume2 Make false assumptions about go -- size of captured group ignored
- echo Echo input line back
- clean Clean out hash table after every command - saves space
- tex Output all formulas in TeX. TeX macros \neg, \Up, \Upup,
- \Down, \Downdown, \UpN{n}, \DownN{n}, \Star, \Tiny{G}, \Miny{G}
- are used, and should be defined by your TeX.
- stat Give hash table and list statistics - (debugging tool)
- SHAR_EOF
- fi
- if test -f 'Makefile'
- then
- echo shar: "will not over-write existing file 'Makefile'"
- else
- cat << \SHAR_EOF > 'Makefile'
- # Copyright (C) David Wolfe, 1990. All rights reserved.
-
- CFLAGS =
- OBJ = hash.o list.o operations.o output.o rational.o grammar.o corridors.o domino.o bitmatrix.o
- CC = gcc
- CFLAGS_ = -g
- CFLAGS = $(CFLAGS_) -Wall
- YFLAGS =
- CFILES = rational.c list.c hash.c operations.c output.c games.c main.c corridors.c domino.c bitmatrix.c
- HFILES = externs.h rational.h list.h hash.h operations.h output.h corridors.h domino.h bitmatrix.h
- ALL = $(CFILES) $(HFILES) HELP Makefile README grammar.y parse.l
-
- all: games
-
- tags:
- etags $(CFILES) $(HFILES) grammar.y parse.l
-
- bundle: $(ALL)
- rm -f .bundle
- bundle $(ALL) > .bundle
-
- games: $(OBJ) Makefile main.o
- $(CC) $(CFLAGS) -o games $(OBJ) main.o
-
- ibm: ibm.c
- gcc ibm.c -o ibm
-
- ibm.c: Makefile $(HFILES) $(CFILES)
- rm -f ibm.c
- echo "#include <stdio.h>" > ibm.c
- cat $(HFILES) $(CFILES) | grep -v "include" >> ibm.c
- awk "/parse.c/ {exit}; {print}" grammar.c | grep -v "include" >> ibm.c
- cat parse.c | grep -v "include" >> ibm.c
- awk "a==1 {print}; /parse.c/ {a=1}" grammar.c | grep -v "include" >> ibm.c
-
- .y.o:
- $(YACC) $(YFLAGS) $<
- $(CC) $(CFLAGS) -c y.tab.c
- 'mv' y.tab.c $*.c
- 'mv' y.tab.o $@
-
- grammar.o: parse.c externs.h rational.h list.h operations.h output.h corridors.h domino.h
- $(CC) $(CFLAGS_) -c grammar.c
-
- parse.c: parse.l
- grammar.c: grammar.y parse.c
- hash.o: externs.h list.h hash.h
- list.o: externs.h list.h
- operations.o: externs.h rational.h hash.h list.h operations.h output.h
- output.o: externs.h rational.h list.h operations.h output.h
- rational.o: externs.h rational.h
- main.o: externs.h rational.h list.h hash.h operations.h output.h games.c
- corridors.o: externs.h list.h hash.h rational.h operations.h corridors.h output.h
- domino.o: externs.h list.h hash.h rational.h operations.h domino.h bitmatrix.h
- bitmatrix.o: bitmatrix.h bitmatrix.c
- SHAR_EOF
- fi
- if test -f 'README'
- then
- echo shar: "will not over-write existing file 'README'"
- else
- cat << \SHAR_EOF > 'README'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- David Wolfe's games program summary
-
- This code implements most of combinatorial game theory found in
- Winning Ways, and other references are listed at the end of this file.
-
- My electronic mail address is wolfe@mandolin.Berkeley.EDU, if you want
- a copy to install. To run, type "games", and at the prompt simply
- type in most reasonable formats for games you've seen. The most
- unusual format is +[3] which is "tiny 3". You can assign and use
- variables, including in the middle of partial results. For example,
- "a = +[b=4]" sets a to +[4] and b to 4. Also, you have some control
- over what is recognized as canonical form for output. For instance,
- if you type the command "no tinys", then +[2] will get printed out as
- "0||0|-2". (By default it tries to recognize as much as possible.)
- Variables you've assigned at one stage show up later in other games'
- canonical forms. "no variables" turns this option off.
-
- For example:
- a=2|1 outputs a = 2|1
- b=3||2|1 outputs b = 3|a
-
- ----------------------------------------------------------------
- PLEASE let me know of comments/bugs/suggestions/etc.
- ----------------------------------------------------------------
- Installation:
-
- Set variables in externs.h if you want the help command to work.
-
- type "make". If you're using ansi-C, you might want to remove
- the commented out type declarations in the .h files for
- debugging.
-
- HELP for semi-complete summary of commands. TODO for improvements
- likely to be done. Again, please mail me suggestions that you'd like
- to see beyond what in the TODO file.
- ----------------
- Combinatoric Game Theory references:
-
- Winning Ways, Elwyn R. Berlekamp and John H. Conway and Richard K.
- Guy, Academic Press, New York, 1982.
-
- Blockbusting and Domineering, Elwyn R. Berlekamp, Journal of
- Combinatorial Theory, 1988, Vol 49, No 1, Series A, September 1988.
-
- On Numbers and Games, John H. Conway, Academic Press, London/New York, 1976.
-
- SHAR_EOF
- fi
- if test -f 'bitmatrix.c'
- then
- echo shar: "will not over-write existing file 'bitmatrix.c'"
- else
- cat << \SHAR_EOF > 'bitmatrix.c'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- #include "externs.h"
- #include "list.h"
- #include "bitmatrix.h"
-
- B_type B_make (int x, int y)
- {
- B_type a;
- int i;
-
- if (!(a = (B_type) malloc (sizeof (struct B_struct))))
- myerror ("B_make: malloc couldn't free block");
- a->x = x;
- a->y = y;
- if (!(a->contents = (unsigned *) malloc (((x*y+(INT_SIZE - 1)) / INT_SIZE) * sizeof (unsigned))))
- myerror ("B_make: malloc couldn't free block");
- for (i = 0; i < (x*y+(INT_SIZE - 1))/INT_SIZE; i++) *(a->contents + i) = (unsigned) 0;
- return a;
- }
-
- list_type B_to_list (B_type a)
- {
- list_type l;
- int i;
-
- l = list_make();
- list_insert_unsorted (l, a->x);
- list_insert_unsorted (l, a->y);
- for (i = 0; i <= (a->x * a->y) / INT_SIZE; i++) list_insert_unsorted (l, *(a->contents + i));
- return l;
- }
-
- B_type B_pack (B_type a)
- {
- B_type b;
- int i, j, xmin, ymin, xmax, ymax;
-
- xmin=a->x, ymin=a->y, xmax=-1, ymax=-1;
- for (i=0; i < a->x; i++)
- for (j=0; j < a->y; j++)
- if (B_get (a,i,j)) {
- if (i < xmin) xmin = i;
- if (j < ymin) ymin = j;
- if (i > xmax) xmax = i;
- if (j > ymax) ymax = j;
- }
- if (xmin == 0 && ymin==0 && xmax==a->x-1 && ymax==a->y-1) return a;
- if (xmin > xmax) {
- B_free (a);
- return B_make (0,0);
- }
- b = B_make (xmax - xmin + 1, ymax - ymin + 1);
- for (i = 0; i < xmax - xmin + 1; i++)
- for (j = 0; j < ymax - ymin + 1; j++)
- if (B_get (a, i+xmin, j+ymin)) B_set (b,i,j);
- B_free (a);
- return b;
- }
-
- void B_printf (B_type a) {
- int x,y;
- for (x = 0; x < a->x; x++) {
- for (y = 0; y < a->y; y++)
- printf ("%d", B_get (a,x,y) ? 1 : 0);
- printf ("\n");
- }
- }
- SHAR_EOF
- fi
- if test -f 'bitmatrix.h'
- then
- echo shar: "will not over-write existing file 'bitmatrix.h'"
- else
- cat << \SHAR_EOF > 'bitmatrix.h'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- /* Maintains an 2 dimensional bit array */
-
- typedef struct B_struct {
- int x;
- int y;
- unsigned *contents;
- } *B_type;
-
- #define SpOt(a,i,j) ((i) * (a)->y + (j))
- #define ByTe(a,i,j) ((a)->contents + (SpOt(a,i,j) / INT_SIZE))
- #define BiT(a,i,j) (SpOt(a,i,j) % INT_SIZE)
-
- #define B_get(a,i,j) ((*ByTe(a,i,j) & (1<<BiT(a,i,j))) != 0)
- #define B_set(a,i,j) ( *ByTe(a,i,j) |= (1<<BiT(a,i,j)))
- #define B_clear(a,i,j) ( *ByTe(a,i,j) &= ~(1<<BiT(a,i,j)))
- #define B_free(a) (free ((a)->contents), free (a))
- #define B_x(a) ((a)->x)
- #define B_y(a) ((a)->y)
-
- extern B_type B_make (int, int);
- extern list_type B_to_list (B_type);
- extern B_type B_pack (B_type);
- extern void B_printf (B_type);
- SHAR_EOF
- fi
- if test -f 'corridors.c'
- then
- echo shar: "will not over-write existing file 'corridors.c'"
- else
- cat << \SHAR_EOF > 'corridors.c'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- /* if (flags & ASSUME_FLAG) is true,
- * We assume that 1) players want to invade/block ONLY the longest
- * blocked or unblocked corridor of a given group. 2) White's
- * invasion of an unblocked corridor is REVERSED throught the blck of
- * that same corridor. */
-
- #include "externs.h"
- #include "list.h"
- #include "hash.h"
- #include "rational.h"
- #include "operations.h"
- #include "corridors.h"
- #include "output.h"
-
- list_type invasion [MAX_INVASIONS];
- #ifdef IBMPC
- unsigned invasions=0;
- #else
- unsigned long invasions=0;
- #endif
- int change_sizes = 1; /* "1/0" means assume size of invading groups "do/don't" matter */
-
- extern void corridor_Print();
-
- void corridor_clear(void) {
- unsigned long i;
-
- for (i = 1; i <= invasions; i++)
- list_free (invasion[i]);
- invasions = 0;
- }
-
- game_type blocked (int n) {
- return plus (g_int (n-2), mult (num (Q_exp (1-n)), one_star));
- }
-
- game_type unblocked (int n) {
- if (n == 0) return zero;
- else if (n == 1) return star (1);
- else return plus (g_int (n-4), mult (num (Q_exp (3-n)), one_star));
- }
-
- int corridor_get (list_type l) {
- if (hash_test (CORRIDOR_KEY, l)) return hash_get_last ();
- if (++invasions >= MAX_INVASIONS) {
- myerror ("corridor_get: No more invasions. Sorry.");
- exit (1);
- }
- invasion[invasions] = list_copy (l);
- hash_put (CORRIDOR_KEY, list_copy (l), invasions);
- return invasions;
- }
-
- static int corridor_size (int i) {
- list_type l;
-
- for (l = list_start (invasion[i]); l != NIL; l = list_rest (l))
- if ((FLAGS & list_pick (l)) == SIZE)
- return (list_pick (l) & DATA);
- myerror ("corridor_size: No Size");
- return 0;
- }
-
- static int corridor_change (int stack[], int o1, int o2, int n1, int n2) {
- list_type inv;
- int i,j;
-
- inv = invasion[i = stack[stack[0]]];
- if (o1 != 0) list_delete (inv, o1);
- if (o2 != 0) list_delete (inv, o2);
- if (n1 != 0) list_insert (inv, n1);
- if (n2 != 0) list_insert (inv, n2);
- j = corridor_get (inv);
- if (n1 != 0) list_delete (inv, n1);
- if (n2 != 0) list_delete (inv, n2);
- if (o1 != 0) list_insert (inv, o1);
- if (o2 != 0) list_insert (inv, o2);
- if (stack[0] > 1) {
- stack[0]--;
- j = corridor_change (stack, FOLLOWER|i, 0, FOLLOWER|j, 0);
- stack[0]++;
- }
- return j;
- }
-
- /* An invasion is a list encoding size, parent, blocked, unblocked, follower */
- /* Function used to construct left and right followers */
- static void corridor_eval (int i, int stack[], list_type left, list_type right) {
- int size, parent=0, long_b=0, long_u=0, followers=0;
- list_type inv, l, l1, l2;
- int n, flgs, data, t;
- game_type g;
-
- if (stack[0] != 1) parent = stack[stack[0]-1];
- inv = list_copy (invasion [i]);
- for (l = list_start (inv); l != NIL; l = list_rest (l)) {
- n = list_pick (l);
- flgs = n & FLAGS;
- data = n & DATA;
- if (flgs == SIZE) size = data;
- else if (flgs == BLOCKED && (data > long_b)) long_b = data;
- else if (flgs == UNBLOCKED && (data > long_u)) long_u = data;
- else if (flgs == FOLLOWER) { /* move on child */
- followers++;
- stack[++stack[0]] = data;
- corridor_eval (data, stack, left, right);
- stack[0]--;
- }
- }
- /* black captures */
- if (long_b + long_u + followers == 0) {
- if (parent != 0) {
- stack[0]--;
- g = corridor_val (corridor_change (stack, FOLLOWER|i,0,0,0));
- stack[0]++;
- }
- else
- g = zero;
- list_insert (left, plus (g, g_int (2 * size)));
- }
- /* white connects to parent*/
- if (parent != 0) {
- l1 = list_copy (inv);
- l2 = list_copy (invasion [parent]);
- list_delete (l1, SIZE | size);
- t = corridor_size (parent);
- if (! (flags & ASSUME2_FLAG)) {
- list_delete (l2, SIZE | t);
- list_insert (l2, SIZE | (t + size + 1));
- }
- list_delete (l2, FOLLOWER | i);
- t = corridor_get (l = list_multi_union (l1, l2));
- if (stack[0] > 2) {
- stack[0] -= 2;
- t = corridor_change (stack, FOLLOWER|stack[stack[0]+1],0,FOLLOWER|t,0);
- stack[0] += 2;
- }
- list_insert (right, corridor_val (t));
- list_free (l);
- list_free (l1);
- list_free (l2);
- } else {
- g = zero;
- for (l = list_start (inv); l != NIL; l = list_rest (l)) {
- n = list_pick (l);
- flgs = FLAGS & n;
- data = DATA & n;
- if (flgs == BLOCKED) g = plus (g, blocked (data));
- else if (flgs == UNBLOCKED) g = plus (g, unblocked (data));
- else if (flgs == FOLLOWER) g = plus (g, corridor_val (data));
- }
- list_insert (right, g);
- }
- list_free (inv);
- if (long_b > 0) {
- /* black blocks longest blocked */
- list_insert (left, plus (g_int (long_b - 1), corridor_val (corridor_change (stack,long_b|BLOCKED,0,0,0))));
- /* white invades longest blocked */
- list_insert (right, corridor_val (corridor_change (stack, long_b|BLOCKED, size|SIZE,long_b==1? 0 : BLOCKED|(long_b-1),
- (size+(flags & ASSUME2_FLAG ? 0 : 1))|SIZE)));
- }
- if (long_u == 1) myerror ("Corridor_eval: Unblocked corridor length 1");
- else if (long_u > 1) {
- /* black blocks longest unblocked */
- list_insert (left, plus (blocked (long_u-1), corridor_val (corridor_change (stack,UNBLOCKED|long_u,0,0,0))));
- if (! (flags & ASSUME_FLAG)) /* This move should be dominated ?? */
- list_insert (left, corridor_val (corridor_change (stack, UNBLOCKED|long_u, 0, BLOCKED|(long_u-1), 0)));
- /* white invades longest unblocked */
- if ((flags & ASSUME_FLAG) || (long_u == 2)) {
- /* Here we assume move reverses */
- g = plus (corridor_val (corridor_change (stack, UNBLOCKED|long_u,0,0,0)), blocked (long_u-2));
- for (l = list_start (right_options (g)); l!=NIL; l=list_rest (l))
- list_insert (right, list_pick (l));
- } else
- list_insert (right, corridor_val (corridor_change (stack, UNBLOCKED|long_u, 0, UNBLOCKED|(long_u-1), 0)));
- }
- return;
- }
-
- game_type corridor_val (int i) {
- list_type left, right;
- int stack[MAX_DEPTH];
- game_type g;
-
- if (hash_test (CORRIDOR_VALUE_KEY, list_1 (i))) return hash_get_last();
- stack[0] = 1;
- stack[1] = i;
- left = list_make();
- right = list_make();
- corridor_eval (i, stack, left, right);
- g = make (left, right);
- hash_put (CORRIDOR_VALUE_KEY, list_copy_1 (i), g);
- return g;
- }
-
- void corridor_Print (int i) {
- int n, data, flgs;
- list_type l;
- printf ("(");
- for (l = list_start (invasion[i]); l != NIL; l = list_rest (l)) {
- n = list_pick (l);
- flgs = n & FLAGS;
- data = n & DATA;
- if (flgs == SIZE) printf ("%d", data);
- else if (flgs == BLOCKED) printf ("b%d", data);
- else if (flgs == UNBLOCKED) printf ("u%d", data);
- else if (flgs == FOLLOWER) corridor_Print (data);
- }
- printf (")");
- }
-
- void corridor_printf (int i) {
- corridor_Print (i);
- printf ("\n");
- }
-
- int corridor_stat (void) {
- unsigned long i,n=0;
-
- for (i = 1; i <= invasions; i++)
- n = n + list_length (invasion[i]) + 1;
- printf ("corridors: %d\n", n);
- return n;
- }
- SHAR_EOF
- fi
- if test -f 'corridors.h'
- then
- echo shar: "will not over-write existing file 'corridors.h'"
- else
- cat << \SHAR_EOF > 'corridors.h'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- /* Uses games package to compute values of corridors in go. A
- position represents a (white) tree of invading groups, each of
- which needs one move to connect to its parent, whose other
- liberties are (black) "blocked" and "unblocked" corridors of
- territory. -- Best expained by example. */
-
- /*
- ....|.|
- ...XXXO...
- ...X.X.X|.
- |..X.X.XX.
- OOOX.XOOXX
- O..OOO.O.X
- */
-
- /* Here every group with a | next to it is alive (immortal). There
- are two white invading groups: The first is 3 stones attacking a
- "blocked" corridor of length 3 and needs one move to connect to
- life. The second is 3 stones attacking an "unblocked" corridor of
- length 2 and a "blocked" corridor of length 1, and needs one move
- to connect to the first invading group. */
-
- /* The input format for this position is
- corridor (3b3 (3b1u2))
- In general, there is a left paren, followed by the size of a
- group followed by a list of liberties, followed by a close paren.
- Each liberty can either be a blocked corridor -- a "b" followed by
- a length, or an unblocked (u), or another invading group which
- needs to connect to the current ((3b1u2) in the current example).
- */
-
- extern int corridor_get(list_type);
- extern game_type corridor_val(int);
- extern void corridor_printf (int);
- extern void corridor_clear (void);
-
- #define F1 (1<<(INT_SIZE-1))
- #define F0 (1<<(INT_SIZE-2))
- #define FLAGS (F0 | F1)
- #define SIZE (0)
- #define BLOCKED (F0)
- #define UNBLOCKED (F1 | F0)
- #define FOLLOWER (F1)
- #define DATA (F0 - 1)
- #define MAX_DEPTH 10
- #define MAX_INVASIONS (MAX_SIZE < DATA ? MAX_SIZE : DATA)
- SHAR_EOF
- fi
- if test -f 'domino.c'
- then
- echo shar: "will not over-write existing file 'domino.c'"
- else
- cat << \SHAR_EOF > 'domino.c'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- #include <stdio.h>
- #include "externs.h"
- #include "list.h"
- #include "hash.h"
- #include "rational.h"
- #include "operations.h"
- #include "output.h"
- #include "bitmatrix.h"
- #include "domino.h"
-
- /* Don't forget to free up space */
-
- game_type place_domino (B_type, int, int, int, int);
- void copy_connected_component_at (B_type, B_type, int, int);
-
- game_type domino_position (B_type pos)
- {
- game_type g;
- int i, j;
- list_type left, right, l;
-
- left=list_make();
- right=list_make();
- l = B_to_list (pos);
- if (hash_test (DOMINO_KEY, l)) return list_free (l), hash_get_last();
- for (i = 0; i < B_x(pos); i++)
- for (j = 0; j < B_y(pos); j++)
- if (B_get (pos, i, j)) {
- if ((i+1 < B_x(pos)) && B_get(pos, i+1, j))
- list_insert (right, place_domino (pos, i,j, i+1,j));
- if ((j+1 < B_y(pos)) && B_get(pos, i, j+1))
- list_insert (left, place_domino (pos, i,j, i,j+1));
- }
- g = make (left, right);
- hash_put (DOMINO_KEY, l, g);
- return g;
- }
-
- game_type place_domino (B_type pos, int x1, int y1, int x2, int y2)
- {
- game_type g;
- B_type new, old;
- int i, j;
- boolean done_something;
-
- g = zero;
- old = B_make (B_x(pos), B_y(pos));
- for (i = 0; i < B_x(old); i++)
- for (j = 0; j < B_y(old); j++)
- if (B_get (pos,i,j)) B_set (old,i,j);
- B_clear (old, x1, y1);
- B_clear (old, x2, y2);
- for (done_something=TRUE;done_something;) {
- done_something=FALSE;
- for (j = 0; j < B_y(old); j++)
- for (i = 0; i < B_x(old); i++)
- if (B_get (old, i, j)) {
- new = B_make(B_x(old),B_y(old));
- copy_connected_component_at (old, new, i, j);
- new = B_pack (new);
- g = plus (g, domino_position (new));
- B_free (new);
- done_something = TRUE;
- }
- }
- B_free (old);
- return g;
- }
-
- int pos_x[]={1,0,-1,0};
- int pos_y[]={0,1,0,-1};
- void copy_connected_component_at (B_type old, B_type new, int x, int y)
- {
- int i,j,n;
-
- B_clear (old, x, y);
- B_set (new, x, y);
- for (n = 0; n <= 3; n++) {
- i = x + pos_x[n];
- j = y + pos_y[n];
- if (i >= 0 && j >= 0 && i < B_x(old) && j < B_y(old) && B_get (old,i,j))
- copy_connected_component_at (old, new, i, j);
- }
- }
-
- B_type input_domino(void)
- {
- B_type pos;
- char s[MAXBUFF];
- int i=0, j;
-
- pos = B_make(DOMINO_INPUT_SIZE,DOMINO_INPUT_SIZE);
- printf ("Enter domineering position followed by extra <cr>\n");
- for (j=0; gets(s) != NULL && *s != '\0';j++) {
- for (i=0; *(s+i) != '\0'; i++)
- if (*(s+i) != ' ') B_set (pos, i, j);
- }
- if (j==0 && i==0) return (B_type) NULL;
- else return B_pack(pos);
- }
-
- static int dc_x (int x, int y, int i) {
- int m, n;
- if (x == 0) { /* domineering chain hardwired: over : 3x4x3x3 */
- n = i%9;
- return n <= 2 ? n :
- n <= 5 ? 2 :
- n <= 7 ? 7-n :
- 0;
- }
- m = i/(x+y-2);
- n = i%(x+y-2);
- if (n<x-1) return (x-1)*m + n;
- else return (x-1)*(m+1);
- }
-
- static int dc_y (int x, int y, int i) {
- int m, n;
- if (x == 0) {
- m = i/9;
- n = i%9;
- return n <= 2 ? m*5 :
- n <= 5 ? m*5 + n-2 :
- n <= 7 ? m*5 + 3 :
- m*5 + n-4;
- }
- m = i/(x+y-2);
- n = i%(x+y-2);
- if (n<x-1) return (y-1)*m;
- else return (y-1)*m + (n-(x-1));
- }
- #define X(i) dc_x (x,y,(i))
- #define Y(i) dc_y (x,y,(i))
- game_type domino_chain (int x, int y, int from, int to) {
- B_type a;
- int i, fx, fy;
- game_type g;
-
- if (to <= from) return zero;
- fx = (x==0 ? 0 : X(from));
- fy = Y(from);
- a = B_make (x == 0 ? 3 : X(to)-fx+1, Y(to)-fy+1);
- for (i = from; i <= to; i++)
- B_set (a, X(i)-fx, Y(i)-fy);
- g = domino_position (a);
- B_free (a);
- return g;
- }
-
- game_type domino (list_type l)
- {
- int x, y, from, to, length, last, width;
- B_type pos;
- char s[MAXBUFF];
- game_type g;
-
- length = list_length (l);
- if (length == 0) {
- pos = input_domino();
- g = domino_position (pos);
- B_free (pos);
- return g;
- }
- if (length == 1) {
- myerror ("Domineering position with 1 arg");
- return NO_GAME;
- }
- last=0;
- x = list_nth (l, 1);
- y = list_nth (l, 2);
- if (length == 2) {
- width = (x == 0 ? 9 : x+y-2);
- printf ("\n%dx%d domineering chain - period %d, saltus %s", x, y, period, game_sprintn (s,saltus, 20));
- if (flags & EVALUATE_FLAG) printf (", warming function: %s", warm_string);
- else printf ("\n");
- printf ("%3s |",""); for (from=0; from < width; from++) printf (" %8", from+1); printf ("\n");
- printf ("---------------------------------------------------------------------------------------\n");
- for (to=0; (to <= last*3 || to <= 10) && to <= 200; to++) {
- printf ("%3d |", to+1);
- for (from=0; from < width; from++) {
- g = domino_chain (x,y,from,to);
- if (to>period && eq (g, plus (domino_chain (x,y,from,to-period), saltus)))
- *s='\0';
- else {
- game_sprintn (s, g, MAXBUFF);
- last = to;
- } printf (" %8s", s);
- }
- printf ("\n");
- fflush (stdout);
- }
- return NO_GAME;
- }
- from = list_nth (l, 3);
- if (length == 3) {
- printf ("%3s | %d by %d domineering chain starting with the %d'th square\n", " ", x, y, from);
- printf ("---------------------------------------------------------------------------------------\n");
- from--;
- for (to=0; (to<=last*3 || to<=10) && to < 100; to++) {
- g = domino_chain (x,y,from,to);
- if (to>period && eq (g, plus (domino_chain (x,y,from,to-period), saltus))) *s = '\0';
- else game_sprintn (s, g, MAXBUFF), last=to;
- printf ("%3d | %s", to+1, s);
- printf ("\n");
- fflush (stdout);
- }
- return NO_GAME;
- }
- to = list_nth (l, 4);
- if (length == 4)
- return domino_chain (x,y,from,to);
- myerror ("domino with more than 4 arguments");
- return NO_GAME;
- }
- SHAR_EOF
- fi
- if test -f 'domino.h'
- then
- echo shar: "will not over-write existing file 'domino.h'"
- else
- cat << \SHAR_EOF > 'domino.h'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- /* Evaluates domineering positions:
- for example, the position
- X
- X
- XX
- is worth 1/2, and is also represented as the chain
- x=3, y=2, from=1, to=4.
- */
- #define DOMINO_INPUT_SIZE 20
-
- extern game_type domino (list_type);
- extern game_type domino_position (B_type);
- extern B_type input_domino(void);
- SHAR_EOF
- fi
- if test -f 'externs.h'
- then
- echo shar: "will not over-write existing file 'externs.h'"
- else
- cat << \SHAR_EOF > 'externs.h'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- #ifndef IBMPC
- /* These variables need to be set */
- /* Delete lines defining PRINT_FILE and HELP_FILE if non-existent or */
- /* on machines which don't have exec() and fork() and the like */
- #define PRINT_FILE "/usr/ucb/more"
- #define HELP_FILE "/home/harmony/users/theory/wolfe/research/games/HELP"
- #endif
-
- #include <string.h>
- #include <stdlib.h>
-
-
- #ifdef Ibm
- #define MAX_SIZE 3000
- #define INT_SIZE 16
- #else
- #define MAX_SIZE 32000
- #define INT_SIZE 32
- #endif
-
- #define FALSE 0
- #define TRUE 1
-
- #define MAXBUFF 200
-
- /* print options */
- #define INTEGERS_FLAG (1<<0)
- #define NUMBERS_FLAG (1<<1)
- #define STARS_FLAG (1<<2)
- #define UPS_FLAG (1<<3)
- #define TINYS_FLAG (1<<4)
- #define ONS_FLAG (1<<12)
- #define VARS_FLAG (1<<5)
- #define EXPAND_FLAG (1<<6)
- #define ALL_FLAG (INTEGERS_FLAG|NUMBERS_FLAG|STARS_FLAG|UPS_FLAG|TINYS_FLAG|ONS_FLAG|\
- VARS_FLAG|EXPAND_FLAG|PROMPT_FLAG|NORMALIZE_FLAG)
- #define PROMPT_FLAG (1<<7)
- /* check if g = h.1* */
- #define EVALUATE_FLAG (1<<8)
- #define NORMALIZE_FLAG (1<<14)
- #define ECHO_INPUT_FLAG (1<<9)
- /* make unproven assumptions (corridors.c) for efficiency */
- #define ASSUME_FLAG (1<<10)
- /* make false assumptions (corridors.c) for efficiency -- in particular that the size of
- an invading group is irrelevent */
- #define ASSUME2_FLAG (1<<15)
- /* reinitialize hash table between commands */
- #define CLEAN_FLAG (1<<11)
- /* output formulas in TeX */
- #define TEX_FLAG (1<<13)
-
- /* hash table entries */
- #define UNEXPENDABLE_KEYS (1 << 15)
- #define EXPENDABLE_KEYS (1 << 14)
- #define OTHER_KEYS (1 << 13)
- #define SIMPLIFY_KEY ( 1 | UNEXPENDABLE_KEYS)
- #define PLUS_KEY ( 2 | EXPENDABLE_KEYS)
- #define NEGATIVE_KEY ( 3 | EXPENDABLE_KEYS)
- #define GE_KEY ( 4 | EXPENDABLE_KEYS)
- #define NUM_UP_STAR_BABYKO_KEY ( 5 | EXPENDABLE_KEYS)
- #define COOL_KEY ( 8 | EXPENDABLE_KEYS)
- #define TEMPERATURE_KEY ( 9 | EXPENDABLE_KEYS)
- #define FREEZE_KEY (10 | EXPENDABLE_KEYS)
- #define HEAT_KEY (12 | EXPENDABLE_KEYS)
- #define MULT_KEY (13 | EXPENDABLE_KEYS)
- #define AW_KEY (14 | EXPENDABLE_KEYS)
- #define VAR_KEY (15 | UNEXPENDABLE_KEYS)
- #define CORRIDOR_KEY (16 | OTHER_KEYS)
- #define CORRIDOR_VALUE_KEY (18 | EXPENDABLE_KEYS)
- #define INT_KO_STAR_KEY (19 | UNEXPENDABLE_KEYS)
- #define INT_BABYKO_KEY (20 | UNEXPENDABLE_KEYS)
- #define DOMINO_KEY (21 | EXPENDABLE_KEYS)
- /* These indicate what to do when hash table needs space.
- OTHER_KEYS are sometimes expendable, depending on context */
-
- /* ARGUMENT_SYMBOL is the internal string representation of the argument to
- cool_function and warm_function. */
- #define ARGUMENT_SYMBOL "\1"
-
- typedef int boolean;
- typedef unsigned game_type;
- typedef game_type (* function_type)();
- typedef boolean (* test_type) (game_type, game_type);
-
- extern void stat ();
- extern void myerror (char *);
- extern int game_parse(char *);
- extern char ** envp;
- extern unsigned long flags;
-
- extern void _exit(int), perror(const char *), execle();
- extern int printf(const char *, ...), vfork(), wait(), yyparse(), fflush();
- extern char *gets();
- #ifdef __TURBOC__
- extern void exit(int), free(void *);
- extern long coreleft(void);
- #endif
- SHAR_EOF
- fi
- if test -f 'games.c'
- then
- echo shar: "will not over-write existing file 'games.c'"
- else
- cat << \SHAR_EOF > 'games.c'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- #include <stdio.h>
- #include "externs.h"
- #include "rational.h"
- #include "list.h"
- #include "hash.h"
- #include "operations.h"
- #include "output.h"
-
- unsigned long flags = ALL_FLAG;
- char **envp;
-
- void myerror(char *s) {
- perror (s);
- }
-
- void help() {
- #ifdef PRINT_FILE
- #ifdef HELP_FILE
- switch (vfork ()) {
- case -1:
- perror ("Sorry, couldn't fork");
- break;
- case 0:
- execle (PRINT_FILE, PRINT_FILE, HELP_FILE, 0, envp);
- perror ("Sorry, couldn't exec");
- _exit (-1);
- default:
- if (wait(0) < 0)
- perror ("wait in help");
- }
- #endif
- #endif
- }
-
- extern char *yysptr;
- extern char yysbuf[];
- int game_parse (char *s) {
- parser_input = s;
- parser_output = NO_GAME;
- if (flags & CLEAN_FLAG) clean();
- yysptr = yysbuf; /* Initialize lex's unput buffer to empty in case
- * last call to yyparse() bombed. */
- if (yyparse()) return NO_GAME;
- else return parser_output;
- }
-
- extern int game_stat();
- extern int hash_stat();
- extern int list_stat();
- extern int corridor_stat();
-
- void stat (void) {
- #ifdef __TURBOC__
- printf ("total lists: %u; coreleft %u\n",
- hash_stat() + game_stat() + corridor_stat() + list_stat(), coreleft());
- #else
- printf ("total lists: %u\n",
- hash_stat() + game_stat() + corridor_stat() + list_stat());
- #endif
- }
-
- void games (void) {
- char input[MAXBUFF];
- game_type g;
-
- printf ("Type help, if you need it, control-D to exit\n");
- for (;;) {
- if (flags & PROMPT_FLAG) printf ("> ");
- if (gets (input) == NULL) {
- printf ("\n");
- exit(0); /* eof */
- }
- if (flags & ECHO_INPUT_FLAG) printf ("%60s => ", input);
- fflush (stdout);
- strcat (input, "\n");
- g = game_parse (input);
- if (g) set_var (dummy_var = make_var ("$"), g);
- if (g) game_printf (g);
- fflush (stdout);
- }
- }
- SHAR_EOF
- fi
- if test -f 'grammar.y'
- then
- echo shar: "will not over-write existing file 'grammar.y'"
- else
- cat << \SHAR_EOF > 'grammar.y'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
- /* Includes mostly code written by David Moews */
-
- %{
- #include "externs.h"
- #include "rational.h"
- #include "list.h"
- #include "operations.h"
- #include "output.h"
- #include "corridors.h"
- #include "bitmatrix.h"
- #include "domino.h"
-
-
- #define vsl(a,b) make(list_copy_1((a)), (b))
- #define vsr(a,b) make((a), list_copy_1((b)))
-
- boolean non_syn_error = FALSE;
- %}
-
- %start line
-
- %union {
- int ival;
- Q_type qval;
- list_type lval;
- game_type gval;
- var_type vval;
- }
-
- %type <vval> vs
- %type <ival> mask c ce
- %type <lval> l cl nl
- %type <gval> num atom atoms numatoms term
- %type <gval> g gt gts line gop gterm
- %type <gval> gp /* plain g (w/o bars in outer level) */
- %type <gval> gb gb1 gb2 gb3 gb4
-
- %token <ival> NUM ZEROS BARZEROS ONNUM
- %token <vval> S
- %token ENDOFSTRING
- %token FREEZE CHILL MEAN TEMPERATURE AW ON OFF
- %token HELP RESET STAT
- %token INTEGERS NUMBERS STARS UPS TINYS ONS VARS EXPAND ALL EVALUATE NORMALIZE PROMPT ECHO_ ASSUME ASSUME2 CLEAN TEX
- %token BAR BARR BARRR BARRRR BARRRRR NO
- %token MINUS_K MINUS_k
- %token TINY MINY
- %token UNKNOWN
- %token CORRIDOR DOMINO SALTUS PERIOD
-
- %%
- line : ENDOFSTRING /*empty*/ { }
- | error ENDOFSTRING {if (!non_syn_error)
- myerror("Syntax error.");
- non_syn_error = FALSE;
- yyerrok;
- }
- | g ENDOFSTRING {parser_output = $1; YYACCEPT;}
- | g '?' g ENDOFSTRING {(void)printf("%s\n", compare($1, $3));
- parser_output = NO_GAME;}
- | mask ENDOFSTRING {flags |= $1;}
- | NO mask ENDOFSTRING {flags &= ~$2;}
- | HELP ENDOFSTRING {(void) help();}
- | STAT ENDOFSTRING {stat();}
- | RESET ENDOFSTRING {reinit();}
- | DOMINO nl ENDOFSTRING {parser_output = domino ($2);}
- | SALTUS ENDOFSTRING {parser_output = saltus; YYACCEPT;}
- | SALTUS g ENDOFSTRING {saltus = $2;}
- | PERIOD ENDOFSTRING {parser_output = g_int (period); YYACCEPT;}
- | PERIOD NUM ENDOFSTRING{period = $2;}
- ;
-
- mask : INTEGERS {$$ = INTEGERS_FLAG;}
- | NUMBERS {$$ = NUMBERS_FLAG;}
- | STARS {$$ = STARS_FLAG;}
- | UPS {$$ = UPS_FLAG;}
- | TINYS {$$ = TINYS_FLAG;}
- | ONS {$$ = ONS_FLAG;}
- | EXPAND {$$ = EXPAND_FLAG;}
- | VARS {$$ = VARS_FLAG;}
- | ALL {$$ = ALL_FLAG;}
- | PROMPT {$$ = PROMPT_FLAG;}
- | EVALUATE {$$ = EVALUATE_FLAG;}
- | NORMALIZE {$$ = NORMALIZE_FLAG;}
- | ECHO_ {$$ = ECHO_INPUT_FLAG;}
- | ASSUME {$$ = ASSUME_FLAG;}
- | ASSUME2 {$$ = ASSUME2_FLAG;}
- | CLEAN {$$ = CLEAN_FLAG;}
- | TEX {$$ = TEX_FLAG;}
- ;
-
- nl : {$$ = list_make();}
- | NUM nl {list_insert_unsorted ($2, $1), $$ = $2;}
-
-
- c : '(' cl ')' {$$ = corridor_get ($2);
- list_free ($2);}
- ;
-
- cl : ce {$$ = list_copy_1 ($1);}
- | cl ce {list_insert ($1, $2); $$ = $1;}
- ;
-
- ce : NUM {$$ = SIZE | $1;}
- | 'b' NUM {$$ = BLOCKED | $2;}
- | 'u' NUM {$$ = UNBLOCKED | $2;}
- | c {$$ = FOLLOWER | $1;}
- ;
-
- l : gt {$$ = list_copy_1($1);}
- | l ',' gt {list_insert ($$ = $1, $3);}
- ;
-
- gb1 : l BAR l {$$ = make($1, $3);}
- | l BAR gb1 {$$ = vsr($1, $3);}
- | ZEROS BAR gt {$$ = zeros_vs ($3, $1);}
- | gt BARZEROS {$$ = vs_zeros ($1, $2);}
- ;
-
- gb2 : gb1 {$$ = $1;}
- | l BARR l {$$ = make($1, $3);}
- | l BARR gb2 {$$ = vsr($1, $3);}
- | gb1 BARR l {$$ = vsl($1, $3);}
- | gb1 BARR gb2 {$$ = vs ($1, $3);}
- ;
-
- gb3 : gb2 {$$ = $1;}
- | l BARRR l {$$ = make ($1, $3);}
- | l BARRR gb3 {$$ = vsr($1, $3);}
- | gb2 BARRR l {$$ = vsl($1, $3);}
- | gb2 BARRR gb3 {$$ = vs ($1, $3);}
- ;
-
- gb4 : gb3 {$$ = $1;}
- | l BARRRR l {$$ = make ($1, $3);}
- | l BARRRR gb4 {$$ = vsr($1, $3);}
- | gb3 BARRRR l {$$ = vsl($1, $3);}
- | gb3 BARRRR gb4 {$$ = vs ($1, $3);}
- ;
-
- gb : gb4 {$$ = $1;}
- | l BARRRRR l {$$ = make ($1, $3);}
- | l BARRRRR gb {$$ = vsr($1, $3);}
- | gb4 BARRRRR l {$$ = vsl($1, $3);}
- | gb4 BARRRRR gb {$$ = vs ($1, $3);}
- ;
-
- g : vs '=' g {set_var($1, $$ = $3);}
- | gts;
- ;
-
- gts : gterm {$$ = $1;}
- | gts '+' gterm {$$ = plus($1, $3);}
- | gts '-' gterm {$$ = minus($1, $3);}
- ;
-
- gterm : gt {$$ = $1;}
- | gb {$$ = $1;}
- ;
-
- gt : gop {$$ = $1;}
- | gp {$$ = $1;}
- | gp '[' g ']' {$$ = cool ($1, mean ($3));}
- | gp '<' g '>' {$$ = gexp ($1, Q_p (mean ($3)));}
- | gp '.' gp {$$ = mult($1, $3);}
- | gp ONNUM {$$ = on ($1, $2);}
- | gt gop {$$ = plus ($1,$2);}
- ;
-
- gop : FREEZE gp {$$ = freeze ($2);}
- | '%' gp {$$ = overheat ($2, NO_GAME, NO_GAME);}
- | '%' '<' g '>' gp {$$ = heat ($5, $3);}
- | '%' '[' g ']' '<' g '>' gp {$$ = overheat ($8, $3, $6);}
- | ON '[' g ']' '<' g '>' {$$ = on ($3, Q_p (mean ($6)));}
- | OFF '[' g ']' '<' g '>' {$$ = off ($3, Q_p (mean ($6)));}
- | CORRIDOR c {$$ = corridor_val ($2);}
- | MEAN gp {$$ = num (mean ($2));}
- | TEMPERATURE gp {$$ = num (temperature ($2));}
- | AW gp {$$ = atomic_weight ($2);}
- ;
-
- num : NUM {$$ = num(Q_int($1));}
- | NUM '/' NUM {Q_error = FALSE;
- $$ = num(Q($1, $3));
- if (Q_error)
- {
- non_syn_error = TRUE;
- YYERROR;
- }
- }
- | '-' vs {$$ = negative (get_var ($2));}
- | '-' NUM {$$ = num(Q_int(-$2));}
- | '-' NUM '/' NUM {Q_error = FALSE;
- $$ = num(Q(-$2, $4));
- if (Q_error)
- {
- non_syn_error = TRUE;
- YYERROR;
- }
- }
- ;
-
- atom : '*' {$$ = star(1);}
- | '*' NUM {$$ = star($2);}
- | '^' {$$ = up(1);}
- | '^' NUM {$$ = up($2);}
- | 'v' {$$ = down(1);}
- | 'v' NUM {$$ = down($2);}
- | TINY '[' g ']' {$$ = tiny ($3);}
- | MINY '[' g ']' {$$ = miny ($3);}
- | 'K' {$$ = ko;}
- | MINUS_K {$$ = kobar;}
- | 'k' {$$ = babyko;}
- | MINUS_k {$$ = babykobar;}
- | '{' g '}' {$$ = $2;}
- | '(' g ')' {$$ = $2;}
- ;
-
- atoms : atom {$$ = $1;}
- | atoms atom {$$ = plus ($1, $2);}
- ;
-
- numatoms: atoms {$$ = $1;}
- | num {$$ = $1;}
- | num atoms {$$ = plus($1, $2);}
- ;
-
- term : numatoms {$$ = $1;}
- /* | numatoms '%' numatoms {$$ = plus ($1, mult ($3, one_star));}*/
- ;
-
- gp : term {$$ = $1;}
- | vs {$$ = get_var($1);
- list_free ($1);
- if ($$ == NO_GAME) {
- myerror("Variable not set.");
- non_syn_error = TRUE;
- YYERROR;
- }
- }
- | '{' l BAR '}' {$$ = make($2, list_make());}
- | '{' BAR l '}' {$$ = make(list_make(), $3);}
- | '{' BAR '}' {$$ = zero;}
- | '{' l BARR '}' {$$ = make($2, list_make());}
- | '{' gb1 BARR '}' {$$ = vsl($2, list_make());}
- | '{' BARR l '}' {$$ = make(list_make(), $3);}
- | '{' BARR gb1 '}' {$$ = vsr(list_make(), $3);}
- | '{' BARR '}' {$$ = zero;}
- | '{' l BARRR '}' {$$ = make($2, list_make());}
- | '{' gb2 BARRR '}' {$$ = vsl($2, list_make());}
- | '{' BARRR l '}' {$$ = make(list_make(), $3);}
- | '{' BARRR gb2 '}' {$$ = vsr(list_make(), $3);}
- | '{' BARRR '}' {$$ = zero;}
- | '{' l BARRRR '}' {$$ = make($2, list_make());}
- | '{' gb3 BARRRR '}' {$$ = vsl($2, list_make());}
- | '{' BARRRR l '}' {$$ = make(list_make(), $3);}
- | '{' BARRRR gb3 '}' {$$ = vsr(list_make(), $3);}
- | '{' BARRRR '}' {$$ = zero;}
- | '{' l BARRRRR '}' {$$ = make($2, list_make());}
- | '{' gb4 BARRRRR '}' {$$ = vsl($2, list_make());}
- | '{' BARRRRR l '}' {$$ = make(list_make(), $3);}
- | '{' BARRRRR gb4 '}' {$$ = vsr(list_make(), $3);}
- | '{' BARRRRR '}' {$$ = zero;}
- ;
-
- vs : S {$$ = $1;}
- ;
- %%
- char *parser_input;
- game_type parser_output;
-
- void yyerror (s)
- char *s;
- {
- }
-
- #include "parse.c"
- SHAR_EOF
- fi
- if test -f 'hash.c'
- then
- echo shar: "will not over-write existing file 'hash.c'"
- else
- cat << \SHAR_EOF > 'hash.c'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- #include "externs.h"
- #include "list.h"
- #include "hash.h"
-
- #define HNIL ((hash_chain_type) 0)
- #define Chain hash_last_chain
-
- long unsigned hash_count=0;
- long unsigned hash_cleanings=0;
- hash_chain_type hash_last_chain;
- static hash_chain_type hash_free_list = HNIL;
- hash_chain_type hash_table[TABLE_SIZE];
-
- static hash_chain_type hash_get_cell (void) {
- hash_chain_type cell, p;
- int i;
-
- if (hash_free_list == HNIL) {
- if (!(hash_free_list = (hash_chain_type)
- malloc(HASH_CELL_BLOCK_SIZE * sizeof (struct hash_chain_struct))))
- myerror("hash_get_cell: malloc couldn't free block");
- for (i = 1, p=hash_free_list; i < HASH_CELL_BLOCK_SIZE;i++, p++)
- p->next = p + 1;
- p++;
- p->next = HNIL;
- }
- cell = hash_free_list;
- hash_free_list = hash_free_list -> next;
- hash_count++;
- return cell;
- }
-
- static void hash_free_cell (hash_chain_type list) {
- list -> next = hash_free_list;
- hash_free_list = list;
- hash_count--;
- }
-
- void hash_init (void) {
- int i;
-
- for (i=0;i<TABLE_SIZE;i++) hash_table[i] = HNIL;
- }
-
- void hash_clear(int keys, int rate) {
- int i;
- static int random=0;
- hash_chain_type chain, next;
-
- for (i = 0; i < TABLE_SIZE; i++) {
- while ((chain = hash_table[i]) != HNIL
- && (chain->id & keys)
- && (random = (random+37) % 100) < rate) {
- hash_table[i] = chain->next;
- list_free (chain->key);
- hash_free_cell (chain);
- }
- if (chain != HNIL) {
- while ((next = chain->next) != HNIL)
- if ( (next->id & keys)
- && (random = (random+37) % 100) < rate) {
- chain->next = next->next;
- list_free (next->key);
- hash_free_cell (next);
- }
- else chain = next;
- }
- }
- }
-
- int hash_function (hash_id_type id, hash_key_type key) {
- unsigned long val;
-
- val = (A * (id%M) + B) % M;
- for (key = list_start (key); key != NIL; key = list_rest (key))
- val = (A * (val + list_pick(key) + 1) + B) % M;
- if (val < 0) val += M;
- return val % TABLE_SIZE;
- }
-
- boolean hash_test (hash_id_type id, hash_key_type key) {
- for (Chain = hash_table[hash_function(id,key)]; Chain != HNIL; Chain = Chain->next)
- if ((Chain->id == id) && list_equal(Chain->key, key))
- return TRUE;
- return FALSE;
- }
-
- #define current_space() ((long) (hash_count * sizeof (struct hash_chain_struct) + list_count * sizeof (struct list_struct)))
- void hash_put (hash_id_type id, hash_key_type key, hash_value_type value) {
- hash_chain_type new;
- int i;
- static long last_cleaned=0, last_warned=0;
-
- if (current_space() > SPACE_CLEAN)
- if (current_space() - last_cleaned > SPACE_INTERVAL) {
- hash_clear (EXPENDABLE_KEYS, 50);
- last_cleaned = current_space();
- hash_cleanings++;
- } else if (current_space() > SPACE_WARNING
- && (current_space() - last_warned > SPACE_INTERVAL)) {
- perror ("WARNING -- running out of space.");
- last_warned = current_space();
- }
- new = hash_get_cell();
- new -> value = value;
- new -> id = id;
- new -> key = key;
-
- i = hash_function(id, key);
- new -> next = hash_table[i];
- hash_table[i] = new;
- return;
- }
-
- hash_value_type hash_get (hash_id_type id, hash_key_type key) {
- for (Chain = hash_table[hash_function(id,key)]; Chain != HNIL; Chain = Chain->next)
- if ((Chain->id == id) && list_equal(Chain->key, key))
- return Chain->value;
- myerror ("hash_get: not in table");
- return 0;
- }
-
- void hash_delete (hash_id_type id, hash_key_type key) {
- hash_chain_type chain, next;
-
- chain = hash_table[hash_function(id,key)];
- if (chain == HNIL) return;
- else if ((chain->id == id) && list_equal(chain->key, key)) {
- hash_table[hash_function(id,key)] = chain -> next;
- list_free (chain->key);
- hash_free_cell (chain);
- } else while ((next = (chain->next)) != HNIL)
- if ((next->id == id) && list_equal(next->key, key)) {
- chain->next = next->next;
- list_free (next->key);
- hash_free_cell (next);
- return;
- } else chain = next;
- return;
- }
-
- unsigned long hash_stat (void) {
- unsigned long n=0, c[30], j, k[30], i;
- hash_chain_type chain;
-
- for (i = 0; i < 30; i++) c[i]=k[i]=0;
- for (i = 0; i < TABLE_SIZE; i++) {
- for (j=0, chain = hash_table[i]; chain != HNIL;j++, chain = chain->next) {
- n = n + list_length (chain->key) + 1;
- (k[chain->id & 31])++;
- }
- if (j < 30)
- c[j]++;
- else
- printf ("Table entry %u has %u elements\n", i, j);
- }
- printf ("Distribution of hash table chains by length:\n");
- for (i = 0; i < 30; i++) printf ("%u ", c[i]);
- printf ("\nDistribution of hash table usage by id:\n");
- for (i = 0; i < 30; i++) printf ("%u ", k[i]);
- printf ("\n");
- printf ("hash cleanings performed: %u; hash table lists: %u; ", hash_cleanings, n);
- return n;
- }
- SHAR_EOF
- fi
- if test -f 'hash.h'
- then
- echo shar: "will not over-write existing file 'hash.h'"
- else
- cat << \SHAR_EOF > 'hash.h'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- /* Hash table implemented using chaining.
- * NOTE: There is only one hash table! The first argument is an integer,
- * which will generally be a unique identifier to which hash you want,
- * simulating multiple hash tables (ie. the real key is constructed from
- * the pair (id, key). The intended purpose is for memoizing
- * functions, in which case the first argument should uniquely identify the
- * function. All functions are written in a type indepenedent manner except
- * hash_fuction().
- */
-
- #define HASH_CELL_BLOCK_SIZE 1000 /* size of mallocs, when needed */
- #define TABLE_SIZE MAX_SIZE
- #define A ((unsigned long) 67343)
- #define B ((unsigned long) 72763)
- #define M ((unsigned long) 99991)
-
- #ifdef IBMPC
- #define SPACE_CLEAN ((long) 200000)
- #define SPACE_INTERVAL ((long) 10000)
- #define SPACE_WARNING ((long) 500000)
- #else
- #define SPACE_CLEAN ((long) 5000000)
- #define SPACE_INTERVAL ((long) 1000000)
- #define SPACE_WARNING ((long) 8000000)
- #endif
-
- typedef game_type hash_value_type;
- typedef int hash_id_type;
- typedef list_type hash_key_type;
-
- typedef struct hash_chain_struct {
- hash_value_type value;
- hash_id_type id;
- hash_key_type key;
- struct hash_chain_struct *next;
- } *hash_chain_type;
-
- extern hash_chain_type hash_table[TABLE_SIZE];
- extern hash_chain_type hash_last_chain;
-
- extern void hash_init (void);
- extern void hash_clear (int, int);
- extern boolean hash_test (hash_id_type, hash_key_type);
- extern void hash_put (hash_id_type, hash_key_type, hash_value_type);
- extern hash_value_type hash_get (hash_id_type, hash_key_type);
- extern void hash_delete (hash_id_type, hash_key_type);
-
- #define hash_get_last() (hash_last_chain->value)
- SHAR_EOF
- fi
- if test -f 'list.c'
- then
- echo shar: "will not over-write existing file 'list.c'"
- else
- cat << \SHAR_EOF > 'list.c'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- #include "externs.h"
- #include "list.h"
-
- long unsigned list_count=0;
- static list_type list_free_list = NIL;
- list_type list_0 = NIL;
- static list_type ll1 = NIL; /* A list of length 1 */
- static list_type ll2 = NIL; /* 2 */
- static list_type ll3 = NIL; /* 3 */
-
- static list_type list_get_cell (void) {
- list_type cell, p;
- int i;
-
- if (list_free_list == NIL) {
- if (!(list_free_list = (list_type)
- malloc(LIST_CELL_BLOCK_SIZE * sizeof (struct list_struct))))
- myerror("list_get_cell: malloc couldn't free block");
- for (i = 1, p=list_free_list; i < LIST_CELL_BLOCK_SIZE;i++, p++)
- p->next = p+1;
- p->next = NIL;
- }
- cell = list_free_list;
- list_free_list = list_free_list->next;
- list_count++;
- return cell;
- }
-
- static void list_free_cell (list_type l) {
- l -> next = list_free_list;
- list_free_list = l;
- list_count--;
- return;
- }
-
- void list_init(void) {
- if (list_0 == NIL) {
- list_0 = list_make();
- ll1 = list_make();
- list_insert (ll1, 0);
- ll2 = list_make();
- list_insert (ll2, 0);
- list_insert (ll2, 0);
- ll3 = list_make();
- list_insert (ll3, 0);
- list_insert (ll3, 0);
- list_insert (ll3, 0);
- }
- return;
- }
-
- list_type list_1(list_elt_type e) {
- ll1->next->elt = e;
- return ll1;
- }
-
- list_type list_unordered_2(list_elt_type e1, list_elt_type e2) {
- if (list_elt_less (e1, e2)) {
- ll2->next->elt = e1;
- ll2->next->next->elt = e2;
- } else {
- ll2->next->elt = e2;
- ll2->next->next->elt = e1;
- }
- return ll2;
- }
-
- list_type list_2(list_elt_type e1, list_elt_type e2) {
- ll2->next->elt = e1;
- ll2->next->next->elt = e2;
- return ll2;
- }
-
- list_type list_3(list_elt_type e1, list_elt_type e2, list_elt_type e3) {
- ll3->next->elt = e1;
- ll3->next->next->elt = e2;
- ll3->next->next->next->elt = e3;
- return ll3;
- }
-
- list_type list_make(void) {
- list_type header;
-
- header = list_get_cell();
- header -> next = NIL;
- list_elt_small (header -> elt);
- return header;
- }
-
- void list_insert (list_type l, list_elt_type e) {
- list_type cell;
-
- while (l->next != NIL && (list_elt_less (l->next->elt, e)))
- l = l->next;
- cell = list_get_cell();
- cell->elt = e;
- cell->next = l->next;
- l->next = cell;
- return;
- }
-
- void list_insert_unsorted (list_type l, list_elt_type e) {
- list_type cell;
-
- cell = list_get_cell();
- cell->elt = e;
- cell->next = l->next;
- l->next = cell;
- return;
- }
-
- boolean list_member (list_type l, list_elt_type e) {
- while ((l = l -> next) != NIL)
- if (list_elt_equal (l->elt, e))
- return TRUE;
- return FALSE;
- }
-
- int list_search (list_type l, list_elt_type e) {
- int i = 0;
-
- while ((l = l->next) != NIL) {
- i++;
- if (list_elt_equal (l->elt, e))
- return i;
- }
- return 0;
- }
-
- int list_length (list_type l) {
- int i = 0;
-
- while ((l = l->next) != NIL)
- i++;
- return i;
- }
-
- void list_delete (list_type l, list_elt_type e) {
- list_type temp;
-
- while (l->next != NIL && ! list_elt_equal (e, l->next->elt))
- l = l->next;
- if (!list_elt_equal (e, l->next->elt)) {
- myerror ("list_delete: element not in list");
- return;
- }
- temp = l->next->next;
- list_free_cell (l->next);
- l->next = temp;
- return;
- }
-
- void list_delete_nth (list_type l, int n) {
- list_type temp;
-
- while (l->next != NIL && --n > 0)
- l = l->next;
- if (l->next == NIL) return;
- temp = l->next->next;
- list_free_cell (l->next);
- l->next = temp;
- return;
- }
-
- void list_change_nth_to (list_type l, int n, list_elt_type e) {
- while (l->next != NIL && n-- > 0)
- l = l->next;
- l->elt = e;
- return;
- }
-
- list_elt_type list_first (list_type l) {
- return l->next->elt;
- }
-
- list_elt_type list_nth (list_type l, int n) {
- while ((l->next) != NIL && n-- > 0)
- l = l->next;
- return l -> elt;
- }
-
- void list_free (list_type l) {
- list_type rest;
-
- if (l == NIL) return;
- while ((rest = (l -> next)) != NIL) {
- list_free_cell (l);
- l = rest;
- }
- list_free_cell (l);
- return;
- }
-
- boolean list_equal (list_type l1, list_type l2) {
- for (;;) {
- l1 = l1->next;
- l2 = l2->next;
- if (l1 == NIL && l2 == NIL) return TRUE;
- else if (l1 == NIL || l2 == NIL
- || ! list_elt_equal (l1->elt,l2->elt)) return FALSE;
- }
- }
-
- list_type list_copy (list_type l1) {
- list_type l2, cell, l;
-
- l = l2 = list_make ();
- while ((l1 = l1 -> next) != NIL) {
- cell = list_get_cell ();
- cell->elt = l1->elt;
- l2->next = cell;
- l2 = cell;
- }
- l2->next = NIL;
- return l;
- }
-
- void list_clobber (list_type l1, list_type l2) {
- if (l1->next) list_free (l1->next);
- l1->next = l2->next;
- list_free_cell (l2);
- return;
- }
-
- list_type list_map (function_one_type f, list_type l1) {
- list_type l2;
-
- l2 = list_make ();
- while ((l1 = (l1->next)) != NIL)
- list_insert (l2, (*f)(l1->elt));
- return l2;
- }
-
- list_type list_mapll (function_two_type f, list_type l1, list_type l2) {
- list_type l3;
-
- l3 = list_make();
- while ((l1 = (l1->next)) != NIL && (l2 = (l2->next)) != NIL)
- list_insert (l3, (*f)(l1->elt, l2->elt));
- return l3;
- }
-
- list_type list_mapcomb (function_two_type f, list_type l1, list_type l2) {
- list_type l, l3;
-
- l3 = list_make();
- while ((l1 = (l1->next)) != NIL) {
- l = l2;
- while ((l = (l->next)) != NIL) {
- list_insert (l3, (*f)(l1->elt, l->elt));
- }
- }
- return l3;
- }
-
- list_type list_maplc (function_two_type f, list_type l1, list_elt_type e) {
- list_type l2;
- l2 = list_make();
- while ((l1 = (l1->next)) != NIL)
- list_insert (l2, (*f)(l1->elt, e));
- return l2;
- }
-
- list_type list_mapcl (function_two_type f, list_elt_type e, list_type l1) {
- list_type l2;
- l2 = list_make();
- while ((l1 = (l1 -> next)) != NIL)
- list_insert (l2, (*f)(e, l1->elt));
- return l2;
- }
-
- /* This combines two lists that are assumed to have positive integer elements
- * into a single list, where the elements of the second list are distinguished
- * by negating them. Only use is to map two lists into one so that a game
- * (with lists of left and right followers) can be hashed using the hash
- * function which operates on only a one list argument. * Cluge *
- */
- list_type list_combine (list_type l1, list_type l2) {
- list_type l3;
- l3 = list_copy (l1);
- while ((l2 = (l2 -> next)) != NIL)
- list_insert (l3, -(l2 -> elt));
- return l3;
-
- }
-
- list_type list_union (list_type l1, list_type l2) {
- list_type l3;
- l3 = list_copy (l1);
- while ((l2 = (l2 -> next)) != NIL)
- if (!list_member (l3, l2->elt)) list_insert (l3, l2->elt);
- return l3;
- }
-
- list_type list_multi_union (list_type l1, list_type l2) {
- l1 = list_copy (l1);
- while ((l2 = (l2 -> next)) != NIL)
- list_insert (l1, l2->elt);
- return l1;
- }
-
- int list_stat(void) {
- list_type l;
- unsigned long n=0, t;
-
- if (list_free_list != NIL) n = 1;
- for (l = list_free_list; l->next != NIL; l = l->next) n++;
- t = list_length (list_0) + list_length (ll1) + list_length (ll2) + list_length (ll3) + 4;
- printf ("free list: %u; fixed lists: %u\n", n, t);
- return n + t;
- }
- SHAR_EOF
- fi
- if test -f 'list.h'
- then
- echo shar: "will not over-write existing file 'list.h'"
- else
- cat << \SHAR_EOF > 'list.h'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- /* Maintains a SORTED list of elements. Done with abstract data types,
- * except functions list_elt_less (e1, e2) and list_elt_equal(e1,e2)
- * compare 2 elements, list_elt_copy(e1,e2) copies elt e2 into e1,
- * and list_elt_small makes an element smaller than all other elements.
- * Lastly, list_combine is very implementation dependent for a cluge.
- */
-
- #define LIST_CELL_BLOCK_SIZE 1000 /* size of mallocs, when needed */
- #define list_elt_equal(x,y) (x==y)
- #define list_elt_less(x,y) (x<y)
- #define list_elt_copy(x,y) (x=y)
- #define list_elt_small(x) (x = 0)
-
- typedef int list_elt_type;
- typedef struct list_struct {
- list_elt_type elt;
- struct list_struct *next;
- } *list_type;
-
- #define NIL (list_type) 0
-
- #if 0
- /* There are the politically correct definitions, since the objects
- * involved are really list_elt_type and not game_type. But the
- * only functions that call them pass functions of type
- *
- * game_type (*f)(game_type, game_type),
- *
- * and since unsigned and int (game_type and list_elt_type) are
- * guaranteed to be the same size, there is no harm done.
- *
- * One must always worry about ones-complement and sign-magnitude machines,
- * but since we don't do comparisons or arithmetic (just assignment),
- * we're okay.
- *
- */
- typedef list_elt_type (*function_two_type)(list_elt_type, list_elt_type);
- typedef list_elt_type (*function_one_type)(list_elt_type);
- #else
- /* The politically incorrect but expedient declarations. */
- typedef game_type (*function_two_type)(game_type, game_type);
- typedef game_type (*function_one_type)(game_type);
- #endif
-
- extern long unsigned list_count; /* Number of lists allocated, not on free stack */
-
- extern void list_init(void);
- extern list_type list_make(void);
- /* list_1, list_2, list_3, and list_unordered_2 are functions returning
- * a recycled list of the indicated length. Note that the list gets trashed the
- * next time the functions are called. Used for temporary, fast, access. */
- extern list_type list_0;
- extern list_type list_1 (list_elt_type);
- extern list_type list_2 (list_elt_type, list_elt_type);
- extern list_type list_unordered_2 (list_elt_type, list_elt_type);
- extern list_type list_3 (list_elt_type, list_elt_type, list_elt_type);
- extern void list_insert (list_type, list_elt_type);
- extern void list_insert_unsorted (list_type, list_elt_type);
- extern boolean list_member (list_type, list_elt_type);
- extern int list_search (list_type, list_elt_type);
- extern int list_length (list_type);
- extern void list_delete (list_type, list_elt_type);
- extern void list_delete_nth (list_type, int);
- extern void list_change_nth_to (list_type, int, int);
- extern list_elt_type list_first (list_type);
- extern list_elt_type list_nth (list_type, int);
- extern void list_free (list_type);
- extern boolean list_equal (list_type, list_type);
- extern list_type list_copy (list_type);
- extern void list_clobber (list_type, list_type);
- /* l1 <- l2 contents, clobbering both l1 and l2 old contents */
- extern list_type list_combine (list_type, list_type);
-
- extern list_type list_map (function_one_type, list_type);
- /* mapll acts on corresponding pairs, mapcomb acts on all pairs */
- extern list_type list_mapll (function_two_type, list_type, list_type);
- extern list_type list_mapcomb (function_two_type, list_type, list_type);
- extern list_type list_maplc (function_two_type, list_type, list_elt_type);
- extern list_type list_mapcl (function_two_type, list_elt_type, list_type);
- extern list_type list_union (list_type, list_type);
- extern list_type list_multi_union (list_type, list_type); /* allows for repeats */
-
- extern int list_stat (void);
-
- #define list_copy_1(a) list_copy (list_1 (a))
- #define list_copy_2(a,b) list_copy (list_2 (a,b))
- #define list_copy_unordered_2(a,b) list_copy (list_unordered_2 (a,b))
- #define list_copy_3(a,b,c) list_copy (list_3 (a,b,c))
-
- /* list_start, list_rest and list_pick are used in tandem to step through
- * a list. list_start() returns the beginnging of a list, and list_rest
- * returns successive elements in the list. A return of NIL indicates end
- * of list. Calling list_pick() return the actual element.
- * for (l = list_start (list); l != NIL; l = list_rest (l)) play_with (list_pick (l));
- */
- #define list_start(l) (l->next)
- #define list_rest(l) (l->next)
- #define list_pick(l) (l->elt)
- SHAR_EOF
- fi
- if test -f 'main.c'
- then
- echo shar: "will not over-write existing file 'main.c'"
- else
- cat << \SHAR_EOF > 'main.c'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- #include "games.c"
-
- void main(int argc, char **argv, char **envp_) {
- char input[MAXBUFF];
- int i;
- game_type g;
-
- envp = envp_;
- init();
- if (argc > 1) { /* run a command for each argument, then output last */
- for (i = 1; i < argc; i++) {
- strcpy (input, argv[i]);
- strcat (input, "\n");
- g = game_parse (input);
- }
- game_printf (g);
- } else games();
- }
-
- SHAR_EOF
- fi
- if test -f 'operations.c'
- then
- echo shar: "will not over-write existing file 'operations.c'"
- else
- cat << \SHAR_EOF > 'operations.c'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- /* Kluges for kos (not well thought out -- certainly unproven)
- * are marked with the comment *KLUGED KO* */
-
- #include "externs.h"
- #include "rational.h"
- #include "list.h"
- #include "hash.h"
- #include "operations.h"
- #include "output.h"
- #include "corridors.h"
-
- #define GNIL ((game_cell_type) 0)
- #define nusb(n,u,s,k) num_up_star_babyko(n,u,s,k)
- #define is_nusb(g) is_num_up_star_babyko(g)
-
- game_type saltus;
- int period;
- game_cell_type game_cell[MAX_GAMES]; /* array of pointers to game cells */
- static unsigned long game_cells = 0; /* Total number of game cells used */
- static game_cell_type game_free_list = GNIL;
- static Q_type frozen_temperature;
- static game_type unit;
- static list_type unit_adder = NIL, unit_neg_adder = NIL;
- static int _rstar_;
-
- game_type zero;
- game_type one;
- game_type two;
- game_type neg1;
- game_type one_star;
- game_type ko;
- game_type kobar;
- game_type babyko;
- game_type babykobar;
- var_type dummy_var; /* set_var shouldn't make game point to variable */
-
- static void game_free_cell (game_cell_type cell) {
- cell -> next = game_free_list;
- game_free_list = cell;
- return;
- }
-
- static void game_free (game_type g) {
- list_free (game_cell[g]->left);
- list_free (game_cell[g]->right);
- game_free_cell (game_cell[g]);
- if (g == game_cells) game_cells--;
- return;
- }
-
- static game_cell_type game_get_cell (void) {
- game_cell_type cell, p;
- unsigned i;
-
- if (game_free_list == GNIL) {
- if (!(game_free_list = (game_cell_type)
- malloc (GAME_BLOCK_SIZE * sizeof (struct game_struct))))
- myerror ("game_get_cell: malloc couldn't free block");
- for (i = 1, p=game_free_list; i < GAME_BLOCK_SIZE; i++, p++)
- p->next = p+1;
- p->next = GNIL;
- }
- cell = game_free_list;
- game_free_list = game_free_list->next;
- return cell;
- }
-
- static game_type new_game ()
- {
- if (++game_cells >= MAX_GAMES) {
- myerror ("new_game: No more games. Sorry.");
- exit (1);
- }
- game_cell[game_cells] = game_get_cell();
- game_cell[game_cells]->left = NIL;
- game_cell[game_cells]->right = NIL;
- game_cell[game_cells]->flags = 0;
- game_cell[game_cells]->Num = Q_0;
- game_cell[game_cells]->Star = 0;
- game_cell[game_cells]->Up = 0;
- game_cell[game_cells]->var = NIL;
- game_cell[game_cells]->next = GNIL;
- return (game_type) game_cells;
- }
-
- static game_type dominates (list_type list, game_type g, test_type test) {
- list_type l;
-
- for (l = list_start (list); l != NIL; l = list_rest (l))
- if ((* test) (list_pick (l), g)) return list_pick (l);
- return (game_type) FALSE;
- }
-
-
- static void reverse_reversals (game_type g) {
- game_type h;
- list_type l;
- list_type l2;
-
- for (l = list_start (left_options (g)); l != NIL;) {
- h = dominates (right_options (list_pick (l)), g, le);
- if (h) {
- list_delete (left_options (g), list_pick (l));
- for (l2 = list_start (extended_left_options (h)); l2 != NIL; l2 = list_rest (l2))
- list_insert (left_options (g), list_pick(l2));
- l = list_start (left_options (g));
- }
- else
- l = list_rest (l);
- }
- for (l = list_start (right_options (g)); l != NIL;) {
- h = dominates (left_options (list_pick (l)), g, ge);
- if (h) {
- list_delete (right_options (g), list_pick (l));
- for (l2 = list_start (extended_right_options (h)); l2 != NIL; l2 = list_rest (l2))
- list_insert (right_options (g), list_pick (l2));
- l = list_start (right_options (g));
- }
- else
- l = list_rest (l);
- }
- return;
- }
-
- static void remove_dominated_options (list_type list, test_type test) {
- list_type list2, l, l2;
- game_type g, h;
-
- list2 = list_make();
- for (l = list_start (list); l != NIL; l = list_rest (l))
- if (! (dominates (list2, g = list_pick (l), test))) {
- for (l2 = list_start (list2); l2 != NIL;) {
- h = list_pick (l2);
- l2 = list_rest (l2);
- if ((* test) (g, h))
- list_delete (list2, h);
- }
- list_insert (list2, g);
- }
- list_clobber (list, list2);
- }
-
- static void evaluate (game_type g) {
- game_type l1, l2, l3, r1, r2, r3, h;
- int ls, rs;
- int maxlstar = -1, maxrstar = -1;
- Q_type n;
- int k;
- boolean is_num_equal = TRUE;
- boolean is_all_num_star_babyko = TRUE;
- boolean can_evaluate = TRUE;
- list_type l;
-
- ls = count_left_options (g);
- rs = count_right_options (g);
- l1 = ls >= 1 ? list_nth (left_options (g), 1) : FALSE;
- l2 = ls >= 2 ? list_nth (left_options (g), 2) : FALSE;
- l3 = ls >= 3 ? list_nth (left_options (g), 3) : FALSE;
- r1 = rs >= 1 ? list_nth (right_options (g), 1) : FALSE;
- r2 = rs >= 2 ? list_nth (right_options (g), 2) : FALSE;
- r3 = rs >= 3 ? list_nth (right_options (g), 3) : FALSE;
- n = l1 ? num_value (l1) : r1 ? num_value (r1) : Q_0;
- k = l1 ? babyko_value (l1) : r1 ? babyko_value (r1) : 0;
- for (l = list_start (left_options (g)); l != NIL; l = list_rest (l)) {
- h = list_pick (l);
- if (!Q_eq (num_value (h), n)) is_num_equal = FALSE;
- if (babyko_value (g) != k) can_evaluate = FALSE;
- if (!is_num_star_babyko (h)) is_all_num_star_babyko = FALSE;
- else if (star_value(h) > maxlstar) maxlstar = star_value (h);
- if (!is_evaluated (h)) can_evaluate = FALSE;
- if (has_ko (h)) set_flag (g, HAS_KO_FLAG);
- }
- for (l = list_start (right_options (g)); l != NIL; l = list_rest (l)) {
- h = list_pick (l);
- if (!Q_eq (num_value (h), n)) is_num_equal = FALSE;
- if (babyko_value (g) != k) can_evaluate = FALSE;
- if (!is_num_star_babyko (h)) is_all_num_star_babyko = FALSE;
- else if (star_value (h) > maxrstar) maxrstar = star_value (h);
- if (!is_evaluated (h)) can_evaluate = FALSE;
- if (has_ko (h)) set_flag (g, HAS_KO_FLAG);
- }
- if (!can_evaluate) return;
- else if (!l1 && !r1) nusb (Q_0,0,0,0);
- else if (!r1) nusb (Q_plus (n, Q_1),0,0,0);
- else if (!l1) nusb (Q_minus (n, Q_1),0,0,0);
- else if (is_num (l1) && is_num (r1) && !l2 && !r2)
- if (Q_lt (num_value (l1), num_value (r1)))
- nusb (Q_divide (Q_plus (num_value (l1), num_value (r1)),Q_2),0,0,k);
- else if (is_num_equal) nusb (n,0,1,k);
- else;
- else if (!is_num_equal) return;
- else if (l2 || r2)
- if (is_num_babyko(r1) && !r2 && !l3
- && ( (is_num_star_babyko(l1) && star_value(l1) == 1 && is_num_babyko(l2))
- || (is_num_star_babyko(l2) && star_value(l2) == 1 && is_num_babyko(l1))))
- nusb (n,1,1,k);
- else if (is_num_babyko(l1) && !l2 && !r3
- && ( (is_num_star_babyko(r1) && star_value(r1) == 1 && is_num_babyko(r2))
- || (is_num_star_babyko (r2) && star_value(r2) == 1 && is_num_babyko(r1))))
- nusb (n,-1,1,k);
- else if (is_all_num_star_babyko && ls == rs
- && maxlstar == (ls - 1) && maxrstar == (rs - 1))
- nusb (n,0,ls,k);
- else;
- else if (is_num_babyko (l1) && !l2 && is_nusb (r1) && !r2 && (up_value (r1) >= 0))
- nusb (n, up_value(r1)+1, star_value(r1)^1,k);
- else if (is_num_babyko (r1) && !r2 && is_nusb (l1) && !l2 && (up_value (l1) <= 0))
- nusb (n, up_value(l1)-1, star_value(l1)^1,k);
- return;
- }
-
- static game_type simplify (game_type g) {
- list_type l;
-
- remove_dominated_options (left_options (g), ge);
- remove_dominated_options (right_options (g), le);
- for (l = list_start (left_options (g)); l != NIL; l = list_rest (l))
- if (has_ko (list_pick (l))) set_flag (g, HAS_KO_FLAG);
- for (l = list_start (right_options (g)); l != NIL; l = list_rest (l))
- if (has_ko (list_pick (l))) set_flag (g, HAS_KO_FLAG);
- reverse_reversals (g);
- clear_flag (g, HAS_KO_FLAG);
- remove_dominated_options (left_options (g), ge);
- remove_dominated_options (right_options (g), le);
- l = list_combine (left_options (g), right_options (g));
- if (hash_test (SIMPLIFY_KEY, l)) {
- game_free (g);
- g = hash_get_last();
- list_free (l);
- } else {
- hash_put (SIMPLIFY_KEY, l, g);
- evaluate (g);
- set_flag (g, CANONICAL_FLAG);
- }
- return g;
- }
-
- static int max_star (game_type g) {
- list_type l;
- int n = 0, s;
- if (is_num_up_star (g))
- if (up_value (g) == 0) return star_value (g);
- else return (1 | star_value (g));
- for (l = list_start (left_options (g)); l != NIL; l = list_rest (l)) {
- s = max_star (list_pick (l));
- n = (n >= s ? n : s);
- }
- for (l = list_start (right_options (g)); l != NIL; l = list_rest (l)) {
- s = max_star (list_pick (l));
- n = (n >= s ? n : s);
- }
- return n;
- }
-
- game_type num_up_star_babyko (Q_type n, int u, int s, int k) {
- game_type g;
- list_type l, args;
-
- if (s < 0) s = -s;
- args = list_copy_3 (u,s,k);
- list_insert_unsorted (args, Q_p(n));
- list_insert_unsorted (args, Q_q(n));
- if (hash_test (NUM_UP_STAR_BABYKO_KEY, args)) {
- list_free (args);
- return hash_get_last();
- }
- if (u == 0 && s == 0) { /* numbers */
- if (k == 0 || !Q_is_int (n))
- g = make_canonical ((!Q_is_int(n) || Q_gt(n,Q_0)) /* left */
- ? list_copy_1 (nusb (Q (Q_p(n)-1, Q_q(n)),0,0,k))
- : list_make()
- ,
- (!Q_is_int(n) || Q_lt (n, Q_0)) /* right */
- ? list_copy_1 (nusb (Q (Q_p(n)+1, Q_q(n)),0,0,k))
- : list_make());
- else if (Q_is_int (n)) g = int_babyko (Q_p(n), k);
- } else if (u == 0) { /* num + star */
- g = nusb (n, 0, s-1, k);
- if (s > 1) l = list_copy (left_options (g));
- else l = list_make();
- list_insert (l, g);
- g = make_canonical (l, list_copy (l));
- } else if (u > 0) {
- if (u == 1 && s == 1)
- g = make_canonical (list_copy_2 (nusb (n,0,0,k), nusb (n,0,1,k)),
- list_copy_1 (nusb (n,0,0,k)));
- else g = make_canonical (list_copy_1 (nusb (n,0,0,k)),
- list_copy_1 (nusb (n,u-1,s^1,k)));
- } else /* if (u < 0) */ {
- if (u == -1 && s == 1)
- g = make_canonical (list_copy_1 (nusb (n,0,0,k)),
- list_copy_2 (nusb (n,0,0,k), nusb (n,0,1,k)));
- else g = make_canonical (list_copy_1 (nusb (n,u+1,s^1,k)),
- list_copy_1 (nusb (n,0,0,k)));
- }
- set_flag (g, NUSB_FLAG);
- game_cell[g]->Num = n;
- game_cell[g]->Up = u;
- game_cell[g]->Star = s;
- if (k != 0) {
- set_flag (g, HAS_KO_FLAG);
- set_flag (g, k == 1 ? BABYKO_FLAG : BABYKOBAR_FLAG);
- }
- hash_put (NUM_UP_STAR_BABYKO_KEY, args, g);
- return g;
- }
-
- game_type int_ko_star (int n, int k, int s) {
- game_type g, h;
- int i;
-
- if (s < 0) return int_ko_star (n, k, -s);
- else if (k > 1) return int_ko_star (n+1, k-3, s);
- else if (k < -1) return int_ko_star (n-1, k+3, s);
- else if (k == 0) return num_up_star (Q_int (n), 0, s);
- if (hash_test (INT_KO_STAR_KEY, list_3 (n, k, s)))
- return hash_get_last();
- i = (k == 1 ? n : n-1);
- g = new_game();
- h = new_game();
-
- game_cell[g]->left = list_copy_1 (h);
- game_cell[g]->right = list_copy_1 (plus (g_int (i), star(s)));
- game_cell[g]->Num = Q_int (i);
- game_cell[g]->Star = s;
- set_flag (g, CANONICAL_FLAG);
- set_flag (g, KO_FLAG);
- set_flag (g, HAS_KO_FLAG);
-
- game_cell[h]->left = list_copy_1 (plus (g_int (i+1), star(s)));
- game_cell[h]->right = list_copy_1 (g);
- game_cell[h]->Num = Q_int (i+1);
- game_cell[h]->Star = s;
- set_flag (h, CANONICAL_FLAG);
- set_flag (h, KOBAR_FLAG);
- set_flag (h, HAS_KO_FLAG);
-
- hash_put (INT_KO_STAR_KEY, list_copy_3 (i, 1, s), g);
- hash_put (INT_KO_STAR_KEY, list_copy_3 (i+1, -1, s), h);
- if (k == 1) return g;
- else return h;
- }
-
- game_type int_babyko (int n, int k) {
- game_type g, h;
- if (k > 1) return int_babyko (n+1, k-3);
- else if (k < -1) return int_babyko (n-1, k+3);
- else if (k == 0) return g_int (n);
- if (hash_test (INT_BABYKO_KEY, list_2 (n, k)))
- return hash_get_last();
- g = new_game();
- h = new_game();
-
- game_cell[g]->left = list_copy_1 (h);
- game_cell[g]->right = list_copy_1 (g_int (n+1));
- game_cell[g]->Num = Q_int (n);
- set_flag (g, CANONICAL_FLAG);
- set_flag (g, NUSB_FLAG);
- set_flag (g, BABYKO_FLAG);
- set_flag (g, HAS_KO_FLAG);
-
- game_cell[h]->left = list_copy_1 (g_int (n-1));
- game_cell[h]->right = list_copy_1 (g);
- game_cell[h]->Num = Q_int (n);
- set_flag (h, CANONICAL_FLAG);
- set_flag (h, NUSB_FLAG);
- set_flag (h, BABYKOBAR_FLAG);
- set_flag (h, HAS_KO_FLAG);
-
- hash_put (INT_BABYKO_KEY, list_copy_2 (n, 1), g);
- hash_put (INT_BABYKO_KEY, list_copy_2 (n, -1), h);
- if (k == 1) return g;
- else return h;
- }
-
- void init (void) {
- list_init();
- hash_init();
- zero = make(list_make(), list_make());
- one = g_int (1);
- two = g_int (2);
- neg1 = g_int (-1);
- one_star = plus (g_int (1), star (1));
- ko = int_ko_star (0,1,0);
- kobar = int_ko_star (0,-1,0);
- babyko = int_babyko (0,1);
- babykobar = int_babyko (0,-1);
- mult (zero, one_star);
- heat (zero, one);
- overheat (zero, one_star, one);
- strcpy (chill_string, "g[1]\n");
- strcpy (warm_string, "g.1*\n");
- dummy_var = list_0;
- period = 2;
- saltus = zero;
- }
-
- void game_clear (void)
- {
- game_type g;
-
- for (g = game_cells; g >= 1; g--)
- game_free (g);
- list_free (unit_neg_adder);
- list_free (unit_adder);
- unit_adder = unit_neg_adder = NIL;
- }
-
- void reinit (void) {
- hash_clear(UNEXPENDABLE_KEYS | EXPENDABLE_KEYS | OTHER_KEYS, 100);
- corridor_clear();
- game_clear();
- zero = make(list_make(), list_make());
- one = g_int (1);
- two = g_int (2);
- neg1 = g_int (-1);
- one_star = plus (g_int (1), star (1));
- ko = int_ko_star (0,1,0);
- kobar = int_ko_star (0,-1,0);
- babyko = int_babyko (0,1);
- babykobar = int_babyko (0,-1);
- mult (zero, one_star);
- heat (zero, one);
- overheat (zero, one_star, one);
- }
-
- void clean (void) {
- hash_clear (EXPENDABLE_KEYS | OTHER_KEYS, 100);
- corridor_clear();
- }
-
- game_type make (list_type left, list_type right) {
- game_type g;
-
- g = new_game();
- game_cell[g]->left = left;
- game_cell[g]->right = right;
- g = simplify(g);
- return g;
- }
-
- game_type make_canonical (list_type left, list_type right) {
- game_type g;
- list_type l;
-
- l = list_combine (left, right);
- if (hash_test (SIMPLIFY_KEY, l)) {
- g = hash_get_last();
- list_free (l);
- list_free (left);
- list_free (right);
- } else {
- g = new_game();
- game_cell[g]->left = left;
- game_cell[g]->right = right;
- set_flag (g, CANONICAL_FLAG);
- hash_put (SIMPLIFY_KEY, l, g);
- }
- return g;
- }
-
- boolean is_var (game_type g) {
- var_type v;
-
- v = game_cell[g]->var;
- if (v == NIL) return FALSE;
- if (eq (get_var (v), g)) return TRUE;
- else {
- list_free (v);
- game_cell[g]->var = NIL;
- return FALSE;
- }
- }
-
- boolean is_tiny (game_type g) {
- game_type h;
- return (count_left_options (g) == 1
- && count_right_options (g) == 1
- && eq (nth_left_option (g, 1), zero)
- && (h = nth_right_option (g, 1), TRUE)
- && count_left_options (h) == 1
- && count_right_options (h) == 1
- && eq (nth_left_option (h, 1), zero)
- && lt (nth_right_option (h, 1), zero));
- }
- boolean is_miny (game_type g) {return is_tiny (negative (g));}
-
- static int on_exponent_ (game_type g) {
- game_type h;
- int i;
-
- if (count_left_options (g) != 1 || count_right_options (g) != 1) return 0;
- h = nth_right_option (g, 1);
- g = nth_left_option (g, 1);
- for (i = 1;; i++) {
- if (eq (g, zero)) return i;
- if (count_left_options (g) != 1 || count_right_options (g) != 1) return 0;
- if (!eq (h, nth_right_option (g, 1))) return 0;
- g = nth_left_option (g, 1);
- }
- }
-
- boolean is_on (game_type g) {return (on_exponent (g) > 1) && !is_nusb(g);}
- int on_exponent (game_type g) {
- int i;
-
- if ((i = on_exponent_ (g)) > 0) return i;
- else return on_exponent_ (negative (g));
- }
-
- game_type on_value (game_type g) {
- if (on_exponent_ (g) > 1) return vs (zero, nth_right_option (g, 1));
- else if (on_exponent_ (g) < 1) return negative (on_value (negative (g)));
- else return g;
- }
-
- boolean is_off (g) game_type g; {return is_on (negative (g));}
-
- game_type tiny_value(game_type g) {g=minus (g, num (mean (g)));
- return negative (nth_right_option(nth_right_option (g,1),1));}
- game_type miny_value(game_type g) {g=minus (g, num (mean(g)));
- return nth_left_option (nth_left_option (g,1),1);}
- var_type var_value (game_type g) {return is_var(g) ? game_cell[g]->var : NO_GAME;}
- int ko_value (game_type g) {return _flags(g)&KO_FLAG ? 1 : _flags(g)&KOBAR_FLAG ? -1 : 0;}
- int babyko_value (game_type g) {return _flags(g)&BABYKO_FLAG ? 1 : _flags(g)&BABYKOBAR_FLAG ? -1 : 0;}
-
- boolean is_canonical(game_type g) {return _flags(g) & CANONICAL_FLAG;}
- boolean is_evaluated(game_type g) {return _flags(g) & EVALUATED_FLAG;}
- boolean is_int(game_type g) {return is_num (g) && Q_is_int (num_value (g));}
- boolean is_num(game_type g) {return is_num_star (g) && star_value (g) == 0;}
- boolean is_up(game_type g) {return is_up_star (g) && star_value (g) == 0;}
- boolean is_star(game_type g) {return is_up_star (g) && up_value (g) == 0;}
- boolean is_num_up_star(game_type g) {return is_nusb(g)&&!babyko_value(g);}
- boolean is_num_star(game_type g) {return is_num_up_star (g) && up_value (g) == 0;}
- boolean is_num_up(game_type g) {return is_num_up_star (g) && star_value (g) == 0;}
- boolean is_up_star(game_type g) {return is_num_up_star(g) && Q_eq (num_value (g), Q_0);}
- boolean is_int_ko_star(game_type g) {return (is_num_star(g)&&Q_is_int(num_value(g))&&star_value(g)<=1) || ko_value(g);}
- boolean is_int_ko(game_type g) {return (is_int_ko_star(g) && star_value (g) == 0);}
- boolean is_num_up_star_babyko (game_type g) {return _flags (g) & NUSB_FLAG;}
- boolean is_num_star_babyko (game_type g) {return is_nusb (g) && up_value (g) == 0;}
- boolean is_num_babyko (game_type g) {return is_num_star_babyko (g) && star_value (g) == 0;}
- boolean is_int_babyko(game_type g) {return is_num_babyko (g) && Q_is_int (num_value (g));}
- boolean has_ko(game_type g) {return _flags (g) & HAS_KO_FLAG;}
-
- char *var_sprintn (char *s, var_type v, int n) {
- list_type l;
- char *t;
-
- t = s;
- for (l = list_start (v); l != NIL && n > 0; l = list_rest(l), s++, n--)
- *s = list_pick (l) & 255;
- *s = '\0';
- return t;
- }
-
- game_type plus (game_type g, game_type h) {
- list_type l1, l2, left, right;
- game_type result;
-
- if (is_nusb (g) && is_nusb (h))
- return nusb (Q_plus (num_value (g), num_value (h)),
- up_value (g) + up_value (h),
- star_value (g) ^ star_value (h),
- babyko_value (g) + babyko_value (h));
- else if (eq (g, zero)) return h;
- else if (eq (h, zero)) return g;
- else if (is_int_ko_star (g) && is_int_ko_star (h)) /*KLUGED KO*/
- return int_ko_star (int_value (g) + int_value (h),
- ko_value (g) + ko_value (h),
- star_value (g) ^ star_value (h));
- if (hash_test (PLUS_KEY, list_unordered_2(g,h)))
- return hash_get_last ();
- if (is_num (g) || (is_int_ko_star (g) && has_ko (g))) /*KLUGED KO*/
- result = make (list_mapcl (plus, g, left_options (h)),
- list_mapcl (plus, g, right_options (h)));
- else if (is_num (h) || (is_int_ko_star (h) && has_ko (h))) /*KLUGED KO*/
- result = make (list_maplc (plus, left_options (g), h),
- list_maplc (plus, right_options (g), h));
- else {
- l1 = list_maplc (plus, left_options (g), h);
- l2 = list_mapcl (plus, g, left_options (h));
- left = list_union (l1, l2);
- list_free (l1);
- list_free (l2);
- l1 = list_maplc (plus, right_options (g), h);
- l2 = list_mapcl (plus, g, right_options (h));
- right = list_union (l1, l2);
- list_free (l1);
- list_free (l2);
- result = make (left, right);
- }
- hash_put (PLUS_KEY, list_copy_unordered_2(g,h), result);
- return result;
- }
-
-
- game_type negative (game_type g) {
- game_type result;
-
- if (is_nusb (g)) /*KLUGED KO*/
- return nusb (Q_negative (num_value (g)), - up_value (g),
- star_value (g), - babyko_value (g));
- else if (is_int_ko_star (g)) /*KLUGED KO*/
- return int_ko_star (- int_value (g), - ko_value (g), star_value (g));
- if (hash_test (NEGATIVE_KEY, list_1(g)))
- result = hash_get_last();
- else {
- result = make (list_map (negative, right_options (g)),
- list_map (negative, left_options (g)));
- hash_put (NEGATIVE_KEY, list_copy_1(g), result);
- }
- return result;
- }
-
- game_type minus (game_type g, game_type h) {
- return plus (g, negative (h));
- }
-
- game_type times (int n, game_type g) {
- if (n == 0) return zero;
- else if (n < 0) return times (-n, negative (g));
- else return plus (g, times (n-1, g));
- }
-
- boolean ge (game_type g, game_type h) {
- list_type l, r;
- boolean result = TRUE;
- int t;
- game_type d, gr, hl;
-
- if (eq (g, h)) return TRUE;
- else if (is_nusb (g) && is_nusb (h)) {
- d = minus (g, h);
- if (babyko_value (d) == -1)
- d = minus (d, num (Q (1,2))); /* 0 <= k <= 1/2 */
- if (Q_gt (num_value (d), Q_0)) return TRUE;
- else if (Q_lt (num_value (d), Q_0)) return FALSE;
- else if ((t = up_value (d)) < 0) return FALSE;
- else if (t >= 2) return TRUE;
- else if (t == 1) return star_value (d) != 1;
- else return star_value (d) == 0;
- } else if (is_num (h) && !has_ko (g)) {
- for (l = list_start (right_options (g)); l != NIL; l = list_rest(l))
- if (ge (h, list_pick (l))) return FALSE;
- return TRUE;
- } else if (is_num (g) && !has_ko (h)) {
- for (l = list_start (left_options (h)); l != NIL; l = list_rest(l))
- if (ge (list_pick (l), g))
- return FALSE;
- return TRUE;
- } else if (is_int_ko_star (g) && is_int_ko_star (h)) {
- d = minus (g, h);
- return (int_value (d) > 0 || eq (d, zero) || eq (d, int_ko_star (0,1,1)));
- } else if (hash_test (GE_KEY, list_2(g,h)))
- return (boolean) hash_get_last();
- if (has_ko (g) || has_ko (h)) { /*KLUGED KO*/
- for (r = list_start (right_options (g));
- r != NIL; r = list_rest (r)) {
- t = FALSE;
- gr = list_pick (r);
- for (l=list_start(extended_left_options(gr)); l!=NIL; l=list_rest(l))
- if (ge (list_pick (l), h)) {t = TRUE; break;}
- if (!t) for (l=list_start(extended_right_options(h)); l!=NIL; l=list_rest(l))
- if (ge (gr, list_pick (l))) {t = TRUE; break;}
- if (!t) {result = FALSE; break;}
- }
- if (result) for (r = list_start (left_options (h));
- r != NIL; r = list_rest (r)) {
- t = FALSE;
- hl = list_pick (r);
- for (l=list_start(extended_right_options(hl)); l!=NIL; l=list_rest(l))
- if (ge (g, list_pick (l))) {t = TRUE; break;}
- if (!t) for (l=list_start(extended_left_options(g)); l!=NIL; l=list_rest(l))
- if (ge (list_pick (l), hl)) {t = TRUE; break;}
- if (!t) {result = FALSE; break;}
- }
- } else {
- for (l = list_start (left_options (h)); l != NIL; l = list_rest(l))
- if (ge (list_pick (l), g)) {result = FALSE; break;}
- if (result) for (l = list_start (right_options (g)); l != NIL; l = list_rest(l))
- if (ge (h, list_pick (l))) {result = FALSE; break;}
- }
- if (is_canonical (g) && is_canonical (h))
- hash_put (GE_KEY, list_copy_2(g,h), (int) result);
- return result;
- }
- boolean le(game_type g, game_type h) {return (ge (h, g));}
- boolean eq(game_type g, game_type h) {return g == h;}
- boolean gt(game_type g, game_type h) {return g != h && ge(g,h);}
- boolean lt(game_type g, game_type h) {return g != h && ge(h,g);}
-
-
- char *compare (game_type g, game_type h) {
- boolean a, b;
- a = ge (g, h);
- b = le (g, h);
- if (a && b) return "=";
- else if (a && !b) return ">";
- else if (!a && b) return "<";
- else return "<>";
- }
-
- boolean lmove_ok (game_type g, game_type h) {
- list_type l;
- for (l = list_start (left_options (g)); l != NIL; l = list_rest (l))
- if (ge (h, list_pick (l))) return TRUE;
- return FALSE;
- }
-
- boolean rmove_ok (game_type g, game_type h) {
- list_type l;
- for (l = list_start (right_options (g)); l != NIL; l = list_rest (l))
- if (le (h, list_pick (l))) return TRUE;
- return FALSE;
- }
-
-
- Q_type left_stop (game_type g) {
- Q_type n, m;
- list_type l;
-
- if (is_evaluated (g)) return num_value (g);
- l = list_start (left_options (g));
- if (l == NIL) return Q_minus (right_stop (g), Q_1); /*KLUGED KO*/
- else n = right_stop (list_pick (l));
- while ((l = list_rest (l)) != NIL) {
- m = right_stop (list_pick (l));
- n = (Q_gt (m, n) ? m : n);
- }
- return n;
- }
-
- Q_type right_stop (game_type g) {
- Q_type n, m;
- list_type l;
-
- if (is_evaluated (g)) return num_value (g);
- l = list_start (right_options (g));
- if (l == NIL) return Q_plus (left_stop (g), Q_1); /*KLUGED KO*/
- n = left_stop (list_pick (l));
- while ((l = list_rest (l)) != NIL) {
- m = left_stop (list_pick (l));
- n = (Q_lt (m, n) ? m : n);
- }
- return n;
- }
-
- list_type incentives (game_type g) {
- list_type l1, l2, l3;
-
- l1 = left_incentives (g);
- l2 = right_incentives (g);
- l3 = list_union (l1, l2);
- remove_dominated_options (l3, ge);
- list_free (l1);
- list_free (l2);
- return l3;
- }
-
- list_type left_incentives (game_type g) {return is_int(g) ? list_copy_1 (neg1) : list_maplc (minus, left_options (g), g);}
- list_type right_incentives (game_type g) {return is_int(g) ? list_copy_1 (neg1) : list_mapcl (minus, g, right_options (g));}
-
- game_type cool (game_type g, Q_type n) {
- Q_type low, high, try;
- list_type left, right;
- list_type l;
- game_type gtry, h;
- boolean cold=FALSE;
-
- if (is_num (g) || Q_eq (n, Q_0)) {
- frozen_temperature = Q_0;
- return g;
- } else if (is_evaluated (g)) {
- frozen_temperature = Q_0;
- h = num (num_value (g));
- if (ko_value (g) == 0) return h;
- else return plus (h, ko_value (g) == 1 ? babyko : babykobar);
- }
- /* The following code is complicated by the fact that we want */
- /* to guarantee that the hash table entries are expendable: */
- /* One of FREEZE_KEY and TEMPERATURE_KEY may have been axed! */
- else if (hash_test (FREEZE_KEY, list_1 (g))) {
- h = hash_get_last();
- if (hash_test (TEMPERATURE_KEY, list_1(g)))
- if (Q_ge (n, frozen_temperature = num_value (hash_get_last())))
- if (Q_eq (n, frozen_temperature)) return h;
- else return num (left_stop (h));
- if (Q_eq (n, Q_infinity)) return num (left_stop (h));
- hash_delete (FREEZE_KEY, list_1 (g));
- }
- if (hash_test (TEMPERATURE_KEY, list_1(g))) hash_delete (TEMPERATURE_KEY, list_1(g));
- #if Q_SIZE == INT_SIZE
- if (hash_test (COOL_KEY, list_2 (g, n)))
- return hash_get_last();
- #else
- if (hash_test (COOL_KEY, list_3 (g, Q_p(n), Q_q(n))))
- return hash_get_last();
- #endif
- if (has_ko (g) && Q_le (left_stop (g), right_stop (g))) cold = TRUE; /*KLUGED KO*/
- low = Q_neg1;
- high = n;
- try = (Q_eq (high, Q_infinity) ? Q_0 : high);
- for (;;) {
- left = list_make();
- right = list_make();
- gtry = num (try);
-
- for (l = list_start (left_options (g)); l != NIL; l = list_rest (l))
- list_insert (left, minus (cool (list_pick (l), try), gtry));
- for (l = list_start (right_options (g)); l != NIL; l = list_rest (l))
- list_insert (right, plus (cool (list_pick (l), try), gtry));
- h = make (left, right);
- if (!is_num (h) && ( Q_le (left_stop (h), right_stop (h)) /* frozen */
- || Q_eq (try, n) /* cooled enough */
- || cold)) break; /*KLUGED KO*/
- if (is_num (h)) high = try;
- else low = try;
- try = Q_simplest_number (low, high);
- }
- frozen_temperature = cold ? Q_0 : try; /*KLUGED KO*/
- if (Q_eq (left_stop (h), right_stop (h))) {
- hash_put (FREEZE_KEY, list_copy_1 (g), h);
- hash_put (TEMPERATURE_KEY, list_copy_1 (g), num (frozen_temperature));
- } else
- #if Q_SIZE == INT_SIZE
- hash_put (COOL_KEY, list_copy_2 (g, n), h);
- #else
- hash_put (COOL_KEY, list_copy_3 (g, Q_p(n), Q_q(n)), h);
- #endif
- if (Q_gt (n, frozen_temperature)) return num (left_stop (h));
- else return h;
- }
- Q_type temperature (game_type g) {cool (g, Q_infinity); return frozen_temperature;}
- game_type freeze (game_type g) {return cool (g, temperature (g));}
- Q_type mean (game_type g) {return left_stop (freeze (g));}
-
- game_type overheat (game_type g, game_type s, game_type t) {
- list_type left;
- list_type right;
- list_type l;
- game_type h;
- static game_type last_s, last_t;
-
- if (s == NO_GAME) s = last_s; else last_s = s;
- if (t == NO_GAME) t = last_t; else last_t = t;
- if (is_int (g)) return times (int_value (g), s);
- else if (is_int_babyko (g)) return plus (star(1), plus (times (int_value (g), s), /*KLUGED KO*/
- babyko_value (g) == 1 ? ko : kobar));
- else if (hash_test (HEAT_KEY, list_3 (g, s, t)))
- return hash_get_last();
- left = list_make();
- right = list_make();
- for (l = list_start (left_options (g)); l != NIL; l = list_rest (l))
- list_insert (left, plus (overheat (list_pick (l), s, t), t));
- for (l = list_start (right_options (g)); l != NIL; l = list_rest (l))
- list_insert (right, minus (overheat (list_pick (l), s, t), t));
- h = make (left, right);
- hash_put (HEAT_KEY, list_copy_3 (g, s, t), h);
- return h;
- }
-
- game_type heat (game_type g, game_type t) {
- list_type left, right, l;
- game_type h;
- static game_type last_t;
-
- if (t == NO_GAME) t = last_t; else last_t = t;
- if (is_num (g)) return g;
- else if (hash_test (HEAT_KEY, list_2 (g, t)))
- return hash_get_last ();
- left = list_make();
- right = list_make();
- for (l = list_start (left_options (g)); l != NIL; l = list_rest (l))
- list_insert (left, plus (heat (list_pick (l), t), t));
- for (l = list_start (right_options (g)); l != NIL; l = list_rest (l))
- list_insert (right, minus (heat (list_pick (l), t), t));
- h = make(left, right);
- hash_put (HEAT_KEY, list_copy_2 (g, t), h);
- return h;
- }
-
- game_type _mult (game_type g) {return mult (g, NO_GAME);}
- game_type mult (game_type g, game_type u) {
- game_type h;
- list_type l, left, right;
-
- if (u != NO_GAME) {
- unit = u;
- l = incentives (unit);
- if (unit_adder != NIL) {
- list_free (unit_adder);
- list_free (unit_neg_adder);
- }
- unit_adder = list_mapcl (plus, unit, l);
- unit_neg_adder = list_map (negative, unit_adder);
- list_free (l);
- }
- if (is_int (g)) return times (int_value (g), unit);
- else if (is_int_babyko (g)) return plus (star (1), plus (times (int_value (g), unit), /*KLUGED KO*/
- babyko_value (g) == 1 ? ko : kobar));
- else if (hash_test (MULT_KEY, list_2 (g, unit)))
- return hash_get_last();
- left = list_map (_mult, left_options (g));
- right = list_map (_mult, right_options (g));
- h = make (list_mapcomb (plus, left, unit_adder),
- list_mapcomb (plus, right, unit_neg_adder));
- list_free (left);
- list_free (right);
- hash_put (MULT_KEY, list_copy_2 (g, unit), h);
- return h;
- }
-
- static game_type aw (game_type g) {
- list_type left, right, l;
- game_type g0, h;
- int try;
-
- if (hash_test (AW_KEY, list_1 (g)))
- return hash_get_last();
- left = list_make();
- right = list_make();
-
- for (l = list_start (left_options (g)); l != NIL; l = list_rest (l))
- list_insert (left, minus (aw (list_pick (l)), two));
- for (l = list_start (right_options (g)); l != NIL; l = list_rest (l))
- list_insert (right, plus (aw (list_pick (l)), two));
- g0 = make (left, right);
- if (!is_int (g0)) {
- hash_put (AW_KEY, list_copy_1 (g), g0);
- return g0;
- } else if (gt (g, _rstar_)) {
- for (h = neg1, try = -1;;h = g_int (++try))
- if ((l = list_start (right_options (g))) != NIL) {
- for (; l != NIL; l = list_rest (l))
- if (ge (h, aw (list_pick (l)))) {
- hash_put (AW_KEY, list_copy_1 (g), h = g_int (try+1));
- return h;
- }
- } else {
- hash_put (AW_KEY, list_copy_1 (g), h = g_int (try+1));
- return h;
- }
- } else if (lt (g, _rstar_)) {
- for (h = one, try = 1;; h = g_int (--try))
- if ((l = list_start (left_options (g))) != NIL) {
- for (; l != NIL; l = list_rest (l))
- if (le (h, aw (list_pick (l)))) {
- hash_put (AW_KEY, list_copy_1 (g), h = g_int (try-1));
- return h;
- }
- } else {
- hash_put (AW_KEY, list_copy_1 (g), h = g_int (try - 1));
- return h;
- }
- } else {
- hash_put (AW_KEY, list_copy_1 (g), g0);
- return g0;
- }
- }
-
- game_type atomic_weight (game_type g) {
- _rstar_ = star (max_star (g) + 1);
- return aw (g);
- }
-
- list_type make_var (char *s) {
- int k;
- var_type v;
-
- v = list_make();
- for (k=0; *s!='\0'; s++, k++)
- list_insert (v, (k<<8) | *s);
- return v;
- }
-
- void set_var (var_type v, game_type g) {
- hash_delete (VAR_KEY, v);
- if (!list_equal (v, dummy_var)) {
- list_free (game_cell[g]->var);
- game_cell[g]->var = list_copy (v);
- }
- hash_put (VAR_KEY, v, g);
- }
-
- game_type get_var (var_type v) {
- if (hash_test (VAR_KEY, v)) return hash_get_last();
- else {
- myerror ("get_var: Variable not set.");
- return NO_GAME;
- }
- }
-
- unsigned long game_stat (void) {
- unsigned long n=0, t=0, v=0, nv=0;
- game_type g;
- game_cell_type l;
-
- for (g = 1; g <= game_cells; g++) {
- n = (n
- + (left_options (g) ? count_extended_left_options (g) + 1 : 0)
- + (right_options (g) ? count_extended_right_options (g) + 1 : 0));
- if (game_cell[g]->var != NIL) {
- nv++;
- v = v + list_length (game_cell[g]->var) + 1;
- }
- }
- t = list_length (unit_adder) + list_length (unit_neg_adder) + 2;
- printf ("game option lists: %u; mult lists: %u; variable lists: %u\n", n, t, v);
- printf ("variables: %u; ", nv);
- for (nv=0, l = game_free_list; l != GNIL; l = l->next) nv++;
- printf ("games: %u; total game cells: %u\n", game_cells, game_cells + nv);
- return n + t + v;
- }
-
- game_type zeros_vs (game_type g, int n)
- {
- if (n == 0) return g;
- else if (n < 0) return negative (zeros_vs (g, -n));
- else return vs (zero, zeros_vs (g, n-1));
- }
- game_type vs_zeros(game_type g, int n) {return zeros_vs (negative (g), -(n));}
- game_type vs(game_type g, game_type h) {return make (list_copy_1 (g), list_copy_1 (h));}
- list_type left_options (game_type g) {return ko_value (g) || babyko_value (g) ? list_0 : game_cell[g]->left;}
- list_type right_options(game_type g) {return ko_value (g) || babyko_value (g) ? list_0 : game_cell[g]->right;}
-
- game_type on (game_type g, int n) {
- game_type h;
-
- if (! (count_left_options(g)==1 && count_right_options(g)==1)) {
- myerror ("on: Game not in correct form for on");
- return zero;
- }
- else if (n == 0) return zero;
- else if (n < 0) return negative (on (g, -n));
- else if (eq (nth_left_option (g, 1), zero)) {
- h = vs (on (g, n-1), nth_right_option (g, 1));
- if (!eq (h, plus (on (g, n-1), gexp (g, n))))
- myerror ("on: on and gexp didn't match");
- return h;
- } else if (eq (nth_right_option (g, 1), zero))
- return negative (on (negative (g), n));
- else {
- myerror ("on: Game not in correct form for on");
- return zero;
- }
- }
- game_type off (game_type g, int n) {return on (g, -n);}
- game_type gexp (game_type g, int n) {
- game_type h;
- int i;
-
- if (! (count_left_options(g)==1 && count_right_options(g)==1)) {
- myerror ("gexp: Game not in correct form for gexp");
- return zero;
- }
- else if (n == 0) return zero;
- else if (n < 0) return negative (gexp (g, -n));
- else if (eq (nth_left_option (g, 1), zero)) {
- for (h = nth_right_option (g, 1), i=1; i<n; i++)
- h = minus (h, gexp (g, i));
- return vs (zero, h);
- } else if (eq (nth_right_option (g, 1), zero)) return negative (gexp (negative (g), n));
- else {
- myerror ("gexp: Game not in correct form for gexp");
- return zero;
- }
- }
- SHAR_EOF
- fi
- if test -f 'operations.h'
- then
- echo shar: "will not over-write existing file 'operations.h'"
- else
- cat << \SHAR_EOF > 'operations.h'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- /* Basic definitions of games and operations on games, as in Winning
- * Ways (Berlekamp, Conway, Guy). The functions for adding, negating
- * and comparing games are given here. Most functions are "memoized",
- * meaning they first check if they have been called before with
- * the same arguments before executing. Note that once you do a
- * make (left, right), both lists are no longer guaranteed to exist,
- * although the lists will be freed properly. This is because
- * usually once you do a make, you typically only need to manipulate
- * the resulting game.
- */
-
- /* Be careful about the list allocation and deallocation! A good
- * sample function to look at is plus in operations.c. Note in
- * particular the use of list_unordered_2 and list_copy_unordered_2
- * for hash table lookups. list_unordered_2 is used ONLY for
- * temporary reference. hash_put() needs to be given a list
- * it can keep. In summary, the function which deallocate
- * a list automatically are list_1, list_2, ... (which never
- * really allocate a list to begin with), make, hash_put, vs,
- * and list_clobber. Otherwise you should do a list_free.
- */
-
- #define MAX_GAMES MAX_SIZE /* Maximum number of games permitted */
- #define GAME_BLOCK_SIZE 1000
- #define NO_GAME ((game_type) 0)
- #define CANONICAL_FLAG (1<<0)
- #define NUSB_FLAG (1<<1)
- #define HAS_KO_FLAG (1<<4)
- #define KO_FLAG (1<<6)
- #define KOBAR_FLAG (1<<7)
- #define BABYKO_FLAG (1<<8)
- #define BABYKOBAR_FLAG (1<<9)
- #define EVALUATED_FLAG (NUSB_FLAG|KO_FLAG|KOBAR_FLAG|BABYKO_FLAG|BABYKOBAR_FLAG)
-
- typedef list_type var_type;
-
- typedef struct game_struct {
- list_type left;
- list_type right;
- unsigned flags;
- Q_type Num;
- int Star;
- int Up;
- var_type var; /* Variable pointing to g set by set_var */
- struct game_struct *next;
- } *game_cell_type;
-
- extern game_type saltus;
- extern int period;
- extern game_cell_type game_cell[]; /* shouldn't really be externed -- for debugging */
- extern game_type zero;
- extern game_type one;
- extern game_type two;
- extern game_type neg1;
- extern game_type one_star;
- extern game_type ko;
- extern game_type kobar;
- extern game_type babyko;
- extern game_type babykobar;
- extern char *parser_input;
- extern game_type parser_output;
- extern var_type dummy_var;
-
- extern void init(void);
- extern void reinit(void);
- extern void clean(void);
- extern game_type make (list_type, list_type);
- extern game_type make_canonical (list_type, list_type);
- extern game_type zeros_vs (game_type, int);
- extern game_type vs_zeros (game_type, int);
- extern game_type vs (game_type, game_type);
- extern list_type left_options (game_type);
- extern list_type right_options (game_type);
- /* #define's
- extern unsigned count_left_options (game_type);
- extern unsigned count_right_options (game_type);
- extern game_type nth_left_option (game_type, unsigned);
- extern game_type nth_right_option (game_type, unsigned);
- */
- extern boolean is_canonical (game_type);
- extern boolean is_evaluated (game_type);
- extern boolean is_int (game_type);
- extern boolean is_num (game_type);
- extern boolean is_up (game_type);
- extern boolean is_star (game_type);
- extern boolean is_tiny (game_type);
- extern boolean is_miny (game_type);
- extern boolean is_on (game_type);
- extern boolean is_num_up_star (game_type);
- extern boolean is_num_star (game_type);
- extern boolean is_up_star (game_type);
- extern boolean is_int_ko_star (game_type);
- extern boolean is_int_ko (game_type);
- extern boolean is_num_up_star_babyko (game_type);
- extern boolean is_num_star_babyko (game_type);
- extern boolean is_num_babyko (game_type);
- extern boolean is_int_babyko (game_type);
- extern boolean has_ko (game_type);
- extern char * var_sprintn (char *, var_type, int);
- extern boolean is_var (game_type);
-
- /* #define's
- extern int int_value (game_type);
- extern Q_type num_value (game_type);
- extern int star_value (game_type);
- extern int up_value (game_type);
- */
- extern game_type tiny_value (game_type);
- extern game_type miny_value (game_type);
- extern int on_exponent (game_type);
- extern game_type on_value (game_type);
- extern var_type var_value (game_type);
- extern int ko_value (game_type);
- extern int babyko_value (game_type);
- extern char * var_sprint (char *, var_type);
-
- extern game_type plus (game_type, game_type);
- extern game_type negative (game_type);
- extern game_type minus (game_type, game_type);
- extern game_type times (int, game_type);
-
- extern boolean ge (game_type, game_type); /* greater or equal */
- extern boolean le (game_type, game_type); /* less than or equal */
- extern boolean eq (game_type, game_type);
- extern boolean gt (game_type, game_type);
- extern boolean lt (game_type, game_type);
- extern char * compare (game_type, game_type);
- extern boolean lmove_ok (game_type, game_type);
- extern boolean rmove_ok (game_type, game_type);
-
- /* #define's
- extern game_type g_int (int);
- extern game_type num (Q_type);
- extern game_type star (int);
- extern game_type up (int);
- extern game_type down (int);
- extern game_type tiny (game_type);
- extern game_type miny (game_type);
- */
-
- extern Q_type left_stop (game_type);
- extern Q_type right_stop (game_type);
- extern list_type incentives (game_type);
- extern list_type left_incentives (game_type);
- extern list_type right_incentives (game_type);
-
- extern game_type cool (game_type, Q_type);
- extern Q_type temperature (game_type);
- extern game_type freeze (game_type);
- extern game_type overheat (game_type, game_type, game_type);
- extern game_type heat (game_type, game_type);
- extern game_type mult (game_type, game_type);
- extern Q_type mean (game_type);
- extern game_type atomic_weight ( game_type);
- extern game_type on (game_type, int);
- extern game_type off (game_type, int);
- extern game_type gexp(game_type, int);
-
- /* Variables names are encoded in lists to make use of hash routines */
- extern var_type make_var (char *);
- extern void set_var (var_type, game_type);
- extern game_type get_var (var_type);
-
- extern game_type int_ko_star (int, int, int);
- extern game_type int_babyko (int, int);
- extern game_type num_up_star_babyko (Q_type, int, int, int);
-
- #define _flags(g) (game_cell[g]->flags)
- #define extended_left_options(g) (game_cell[g]->left)
- #define extended_right_options(g) (game_cell[g]->right)
- #define count_left_options(g) list_length (left_options (g))
- #define count_right_options(g) list_length (right_options (g))
- #define count_extended_left_options(g) list_length (extended_left_options (g))
- #define count_extended_right_options(g) list_length (extended_right_options (g))
- #define nth_left_option(g,i) list_nth (left_options (g), i)
- #define nth_right_option(g,i) list_nth (right_options (g), i)
-
- #define num_value(g) (game_cell[g]->Num)
- #define int_value(g) Q_p (num_value (g))
- #define star_value(g) (game_cell[g]->Star)
- #define up_value(g) (game_cell[g]->Up)
-
- #define num_up_star(a,b,c) num_up_star_babyko (a,b,c,0)
- #define num(n) num_up_star ((n), 0, 0)
- #define g_int(n) num (Q_int (n))
- #define star(n) num_up_star (Q_0, 0, (n))
- #define up(n) num_up_star (Q_0, (n), 0)
- #define down(n) negative (up (n))
- #define tiny(g) vs (zero, vs (zero, negative (g)))
- #define miny(g) vs (vs ((g), zero), zero)
- #define set_flag(g,f) (game_cell[g]->flags |= (f))
- #define clear_flag(g,f) (game_cell[g]->flags &= ~(f))
-
- SHAR_EOF
- fi
- if test -f 'output.c'
- then
- echo shar: "will not over-write existing file 'output.c'"
- else
- cat << \SHAR_EOF > 'output.c'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- /* WHOLE_TREE 1
- EVALUATED_TREE 2 */
-
- #include <stdio.h>
- #include "externs.h"
- #include "rational.h"
- #include "list.h"
- #include "operations.h"
- #include "output.h"
-
- char chill_string[MAXBUFF];
- char warm_string[MAXBUFF];
- int expression (char *, game_type, int, boolean, boolean);
-
- boolean is_print_simple (game_type g) {
- static char s[MAXBUFF];
- return !expression (s, g, MAXBUFF-1, FALSE, TRUE);
- }
-
- void game_print (game_type g) {
- static char s[MAXBUFF];
- printf ("%s", game_sprintn (s, g, MAXBUFF-1));
- return;
- }
-
- void game_printf (game_type g) {
- static char s[MAXBUFF];
- printf ("%s\n", game_sprintn (s, g, MAXBUFF-1));
- return;
- }
-
- char *game_sprint (char *s, game_type g) {
- return game_sprintn (s, g, MAXBUFF-1);
- }
-
- static char *strsub (s, old, new)
- char *s;
- char old, new;
- {
- char *t;
- for (t=s; *t != '\0'; t++)
- if (*t == old) *t = new;
- return s;
- }
-
- static game_type warm(game_type g) {
- set_var (dummy_var = make_var (ARGUMENT_SYMBOL), g);
- strsub (warm_string, 'g', *ARGUMENT_SYMBOL);
- g = game_parse (warm_string);
- strsub (warm_string, *ARGUMENT_SYMBOL, 'g');
- return g;
- }
-
- static game_type chill (game_type g) {
- set_var (dummy_var = make_var (ARGUMENT_SYMBOL), g);
- strsub (chill_string, 'g', *ARGUMENT_SYMBOL);
- g = game_parse (chill_string);
- strsub (chill_string, *ARGUMENT_SYMBOL, 'g');
- return g;
- }
-
- #define appendg(g,t) expression (s + strlen (s), g, n - strlen (s), t, TRUE)
- char *game_sprintn (char *s, game_type g, int n) {
- game_type chilled, warmed, frac, gnorm, small;
- Q_type k, k2;
- int t, norm;
-
- strcpy (s, "");
- if (g && (flags & EVALUATE_FLAG)) {
- k = mean (g);
- t=FALSE;
- if (Q_ge (k, 0)) {
- k2 = Q_plus (k, Q(1,2));
- norm = Q_p (k2) / Q_q(k2);
- if (Q_q (k2) == 1) norm--;
- }
- else {
- k2 = Q_minus (k, Q(1,2));
- norm = - ((- Q_p (k2)) / Q_q (k2));
- if (Q_q (k2) == 1) norm++;
- }
- if (!(flags & NORMALIZE_FLAG)) norm = 0;
- chilled = chill (minus (g, g_int (norm)));
- warmed = warm (chilled);
- frac = (has_ko (chilled) || !Q_eq (left_stop (chilled), right_stop (chilled)))
- ? zero : num (mean (chilled));
- small = minus (chilled, frac);
- if ( eq (g, plus (warmed, gnorm = g_int (norm)))
- || eq (g, plus (warmed, gnorm = plus (gnorm, star(1))))) {
- t = flags & EXPAND_FLAG;
- flags = (flags | EXPAND_FLAG) ^ EXPAND_FLAG; /* clear flag */
- if (eq (chilled, zero))
- appendg (gnorm, FALSE);
- else {
- if (!eq (gnorm, zero)) appendg (gnorm, FALSE);
- if (strlen (s) < n) strcat (s, flags & TEX_FLAG ? "\\int " : "%");
- if (!eq (frac, zero)) appendg (frac, FALSE);
- if (!eq (small, zero)) appendg (small, TRUE);
- }
- flags = flags | t;
- } else appendg (g, FALSE);
- } else appendg (g, FALSE);
- return s;
- }
-
- void list_print (list_type l) {
- static char s[MAXBUFF];
- printf ("%s", list_sprintn (s, l, MAXBUFF-1));
- return;
- }
-
- void list_printf (list_type l) {
- static char s[MAXBUFF];
- printf ("%s\n", list_sprintn (s, l, MAXBUFF-1));
- return;
- }
-
- char *list_sprint (char *s, list_type l) {
- return list_sprintn (s, l, MAXBUFF-1);
- }
-
- char *list_sprintn (char *s, list_type l, int n) {
- static char t[20];
-
- strncpy (s, "( ", n - strlen (s));
- while (l->next != NIL) {
- l = l->next;
- sprintf (t,"%d ", l->elt);
- strncat (s, t, n - strlen (s));
- }
- strncat (s, ")", n - strlen (s));
- return s;
- }
-
- #define ss(x) (strncat (s, (x), n - strlen (s)))
- #define sd(x) (sprintf (buff, flags & TEX_FLAG ? " %d" : "%d", (x)), ss(buff))
- #define sg(x) (expression (buff, (x), MAXBUFF-1, FALSE, FALSE), ss (buff))
- #define sgp(x) (expression (buff, (x), MAXBUFF-1, TRUE, FALSE), ss (buff))
- #define sv(x) (var_sprintn (s, var_value (x), n - strlen (s)))
- #define TeX (flags & TEX_FLAG)
- int expression (char *s, game_type g, int n, boolean brace, boolean attop) {
- char buff[MAXBUFF], left[MAXBUFF], right[MAXBUFF];
- int t, bars, lbars=0, rbars=0, i, ls, rs;
- Q_type m;
- game_type h;
-
- strcpy (s, "");
- h = minus (g, num (m = left_stop (g)));
- if ( ((is_tiny (h) || is_miny (h)) && (flags & TINYS_FLAG))
- || ((is_on (h)) && (flags & ONS_FLAG))
- || (is_num_up_star (g)
- && (Q_eq (num_value (g), Q_0) || (flags & INTEGERS_FLAG))
- && (Q_is_int (num_value (g)) || (flags & NUMBERS_FLAG))
- && ((up_value (g) == 0) || (flags & UPS_FLAG))
- && ((star_value (g) == 0) || (flags & STARS_FLAG)))
- || (is_int_ko_star (g) && ko_value (g) != 0)
- || (is_num_up_star_babyko (g) && babyko_value (g) != 0)) {
- if (!Q_eq (m, Q_0) || eq (g, zero)) {
- if (TeX && Q_lt (m, Q_0)) ss ("\\neg"), m = Q_negative (m);
- if (Q_is_int (m)) sd (Q_p(m));
- else if (TeX) (ss ("{"), sd (Q_p(m)), ss ("\\over"), sd (Q_q(m)), ss ("}"));
- else (sd (Q_p(m)), ss ("/"), sd (Q_q(m)));
- }
- if ((t = up_value (g)) != 0)
- if (TeX) {
- if (t == 2) ss ("\\Upup");
- else if (t == -2) ss ("\\Downdown");
- else if (t == 1) ss ("\\Up");
- else if (t == -1) ss ("\\Down");
- else ss (t>0? "\\UpN{" : "\\DownN{"), (t>1? sd (t) : t<-1? sd(-t) :0), ss("}");
- } else ss (t>0? "^" : "v"), (t>1? sd(t) : t<-1? sd(-t) :0);
- if ((ko_value (g)) == 1) ss (TeX ? "\\Ko" : "K");
- if ((ko_value (g)) == -1) ss (TeX ? "\\Kobar" : "-K");
- if ((t = star_value (g)) > 0) (ss (TeX?"\\Star":"*"), t>1? sd (t) :0);
- if (is_tiny (h)) ss (TeX?"\\Tiny{":"+["), sg (tiny_value (h)), ss (TeX?"}":"]");
- if (is_miny (h)) ss (TeX?"\\Miny{":"-["), sg (miny_value (h)), ss (TeX?"}":"]");
- if (is_on (h)) sgp (on_value (h)), ss (TeX?"^{\\to ":"<("), sd (on_exponent (h)), ss (TeX?"}":")>");
- if ((babyko_value (g)) == 1) ss (TeX ? "\\ko" : "k");
- if ((babyko_value (g)) == -1) ss (TeX ? "\\kobar" : "-k");
- return 0;
- } else if ((flags & VARS_FLAG) && is_var (g)) {
- sv (g);
- if (attop && (flags & EXPAND_FLAG)) ss (" = ");
- else return 0;
- }
- /*********** At this point we're looking at a Gl|Gr or {Gl|Gr} **********/
- ls = count_left_options (g);
- rs = count_right_options (g);
- *left = *right = '\0';
- if (ls == 0 || rs == 0) brace = TRUE;
- for (i = 1; i <= ls; i++) {
- t = expression (buff, nth_left_option (g, i), MAXBUFF-2, ls > 1, FALSE);
- if (i < ls) strcat (buff, ",");
- lbars = (t > lbars) ? t : lbars;
- strncat (left, buff, MAXBUFF-1 - strlen (left));
- }
- for (i = 1; i <= rs; i++) {
- t = expression (buff, nth_right_option (g, i), MAXBUFF-2, rs > 1, FALSE);
- if (i < rs) strcat (buff, ",");
- rbars = (t > rbars) ? t : rbars;
- strncat (right, buff, MAXBUFF-1 - strlen (right));
- }
- lbars++;
- rbars++;
- #define E_LBRACE (ss (TeX?"\\{":"{"))
- #define E_RBRACE (ss (TeX?"\\}":"}"))
- #define E_BAR (ss (TeX?"|":"|"))
- bars = (lbars > MAXBARS ? rbars :
- rbars > MAXBARS ? lbars :
- lbars > rbars ? lbars : rbars);
- if (brace) E_LBRACE;
- if (lbars > MAXBARS) E_LBRACE;
- ss (left);
- if (lbars > MAXBARS) E_RBRACE;
- if (bars > MAXBARS) E_BAR;
- else for (i = 1; i <= bars; i++) E_BAR;
- if (rbars > MAXBARS) E_LBRACE;
- ss (right);
- if (rbars > MAXBARS) E_RBRACE;
- if (brace) E_RBRACE;
- return (brace ? 0 : bars > MAXBARS ? 1 : bars);
- }
- SHAR_EOF
- fi
- if test -f 'output.h'
- then
- echo shar: "will not over-write existing file 'output.h'"
- else
- cat << \SHAR_EOF > 'output.h'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- /* Output routines for games: expressions and trees */
- /* Note: I assume sprintf returns length of string */
-
- #define MAXBARS 3
-
- extern char chill_string[MAXBUFF];
- extern char warm_string[MAXBUFF];
-
- extern boolean is_print_simple (game_type);
- extern void game_print (game_type);
- extern void game_printf (game_type);
- extern char * game_sprint (char *, game_type);
- extern char * game_sprintn (char *, game_type, int);
- extern void list_print (list_type);
- extern void list_printf (list_type);
- extern char * list_sprint (char *, list_type);
- extern char * list_sprintn (char *, list_type, int);
- /* extern char * tree (char *, game_type, int, int); (not yet written)*/
- /* extern char * var_sprint (char *, var_type);
- * lies in operations.h */
-
- SHAR_EOF
- fi
- if test -f 'parse.l'
- then
- echo shar: "will not over-write existing file 'parse.l'"
- else
- cat << \SHAR_EOF > 'parse.l'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
- /* Includes mostly code written by David Moews */
-
- %%
- stat {return STAT;}
- freeze {return FREEZE;}
- chill[\n] {printf ("%s", chill_string); return ENDOFSTRING;}
- warm[\n] {printf ("%s", warm_string); return ENDOFSTRING;}
- chill[^\n]*[\n] {strcpy (chill_string, yytext+5); return ENDOFSTRING;}
- warm[^\n]*[\n] {strcpy (warm_string, yytext+5); return ENDOFSTRING;}
- on {return ON;}
- off {return OFF;}
- mean {return MEAN;}
- temperature {return TEMPERATURE;}
- temp {return TEMPERATURE;}
- aw {return AW;}
- integers {return INTEGERS;}
- numbers {return NUMBERS;}
- stars {return STARS;}
- ups {return UPS;}
- tinys {return TINYS;}
- tinies {return TINYS;}
- ons {return ONS;}
- variables {return VARS;}
- expand {return EXPAND;}
- all {return ALL;}
- prompt {return PROMPT;}
- evaluate {return EVALUATE;}
- eval {return EVALUATE;}
- normalize {return NORMALIZE;}
- normal {return NORMALIZE;}
- norm {return NORMALIZE;}
- echo {return ECHO_;}
- assume {return ASSUME;}
- assume2 {return ASSUME2;}
- reset {return RESET;}
- clean {return CLEAN;}
- tex {return TEX;}
- no {return NO;}
- help {return HELP;}
- corridor {return CORRIDOR;}
- corr {return CORRIDOR;}
- cor {return CORRIDOR;}
- domineering {return DOMINO;}
- domineer {return DOMINO;}
- domino {return DOMINO;}
- dom {return DOMINO;}
- saltus {return SALTUS;}
- period {return PERIOD;}
- "|" {return BAR;}
- "||" {return BARR;}
- "|||" {return BARRR;}
- "||||" {return BARRRR;}
- "|||||" {return BARRRRR;}
- "|0<"[0-9]+">" {extern int atoi();
- yylval.ival = atoi(yytext+3);
- return BARZEROS;}
- 0"<"0-9]+">" {extern int atoi();
- yylval.ival = atoi(yytext+2);
- return ZEROS;}
- 0|[1-9][0-9]* {extern int atoi();
- yylval.ival = atoi(yytext);
- return NUM;}
- "<("[1-9][0-9]*")>" {extern int atoi();
- yylval.ival = atoi(yytext+2);
- return ONNUM;}
- [<>%_?\+\(\)\{\}\[\]\.\-\^\*v,\/=Kk] {return *yytext;}
- "-K" {return MINUS_K;}
- "-k" {return MINUS_k;}
- "+"/"[" {return TINY;}
- "-"/"[" {return MINY;}
- [\n] {return ENDOFSTRING;}
- [ \t] {}
- [bu]/[0-9] {return *yytext;}
- v*['\1'$a-uw-zA-Z][a-zA-Z]*[0-9]* {yylval.lval = make_var (yytext);
- return S;}
- . {return UNKNOWN;}
- %%
- int yywrap()
- {
- return 1;
- }
-
- #define my_getc() (*(parser_input++))
- #undef input
- # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):my_getc())==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar)
-
- char *strdup (s)
- char *s;
- {
- char *t, *malloc();
- t = malloc (strlen (s) + 1);
- strcpy (t, s);
- return t;
- }
- SHAR_EOF
- fi
- if test -f 'rational.c'
- then
- echo shar: "will not over-write existing file 'rational.c'"
- else
- cat << \SHAR_EOF > 'rational.c'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- #include "externs.h"
- #include "rational.h"
-
- #define p(x) Q_p(x)
- #define q(x) Q_q(x)
-
- int Q_error=FALSE;
-
- int _Q_to_int (Q_type x) { /* Cast Q_type into int, keeping low order bits */
- int i,y;
- for (i=y=0; i<INT_SIZE; i++, x>>=1)
- if (x & Q_BIT) y|=(1<<i);
- return y;
- }
-
- Q_type _int_to_Q (int x) {
- int i;
- Q_type y=Q_0;
- for (i=0; i<INT_SIZE; i++, x>>=1)
- if (x & 1) y |= (Q_BIT<<i);
- return y;
- }
-
- int Q_q (Q_type x) {
- int q = 1;
- while (!Q_is_int (x)) x <<= 1, q <<= 1;
- return q;
- }
- /* return (Q_is_int (x)) ? 1 OLD CODE
- : Q_to_int (Q_1 / (((x ^ (x-Q_BIT)) + Q_BIT) >> 1));
- */
-
- int Q_p (Q_type x) {
- return Q_to_int (Q_is_int (x) ? x >> Q_SHIFT
- : x / (((x ^ (x-Q_BIT)) + Q_BIT) >> 1));
- }
-
- Q_type Q_times (Q_type x, Q_type y) {
- return Q (p(x)*p(y), q(x)*q(y));
- }
-
- Q_type Q_divide (Q_type x, Q_type y) {
- if (p(y) == 0) myerror ("Q_divide: divide by zero");
- else if (y == Q_2) return x>>1;
- return Q (p(x)*q(y), q(x)*p(y));
- }
-
- Q_type Q_simplest_number (Q_type x, Q_type y) {
- int i;
- Q_type z;
- if (Q_ge (x, y)) {
- myerror ("Q_simplest_number: first argument exceeds second");
- return Q_0;
- }
- else if (Q_lt (x, Q_0)) return Q_gt (y, Q_0) ? Q_0
- : Q_negative (Q_simplest_number (Q_negative (y), Q_negative (x)));
- else if (Q_lt (Q_int(p(x)/q(x) + 1), y)) return Q_int(p(x)/q(x) + 1);
- for (i=1; (x>>i) != (y>>i); i++);
- i--;
- z = ((x >> i) << i);
- if ((z | (Q_BIT<<i)) < y) z |= (Q_BIT << i);
- else while (z <= x && i >= 0) z |= (Q_BIT << --i);
- if (!(x < z && z < y)) myerror ("Q_simplest_number: rational fucked up");
- return z;
- }
-
- void Q_printf (Q_type x) {
- printf ("%d/%d\n", Q_p(x), Q_q(x));
- return;
- }
- SHAR_EOF
- fi
- if test -f 'rational.h'
- then
- echo shar: "will not over-write existing file 'rational.h'"
- else
- cat << \SHAR_EOF > 'rational.h'
- /* Copyright (C) David Wolfe, 1990. All rights reserved. */
-
- /* Does arithmetic on dyadic rationals. */
-
- typedef long Q_type;
- extern int Q_error;
- #define Q_SIZE 32
- #define Q_SHIFT 20
- #define Q_BIT ((Q_type) 1)
-
- #define Q_0 ((Q_type) 0)
- #define Q_1 (Q_BIT << Q_SHIFT)
- #define Q_2 (Q_1 << 1)
- #define Q_neg1 (- Q_1)
- #define Q_infinity (((( Q_BIT << (Q_SIZE-2)) - Q_BIT) << 1) + Q_BIT)
-
- /* Internal use only: don't use these */
- #if (Q_SIZE > INT_SIZE) & !defined(IBMPC)
- extern int _Q_to_int(Q_type);
- extern Q_type _int_to_Q(int);
- #define Q_to_int _Q_to_int
- #define int_to_Q _int_to_Q
- #else
- #define Q_to_int(x) ((int) x)
- #define int_to_Q(x) ((Q_type) x)
- #endif
-
- #define Q(a,b) (int_to_Q(a) * (Q_1 / ((Q_type) b)))
- #define Q_int(a) (int_to_Q(a) << Q_SHIFT)
- #define Q_plus(x,y) ((x)+(y))
- #define Q_negative(x) (-(x))
- #define Q_minus(x,y) ((x)-(y))
- #define Q_ge(x,y) ((x) >= (y))
- #define Q_le(x,y) ((x) <= (y))
- #define Q_eq(x,y) ((x) == (y))
- #define Q_gt(x,y) ((x) > (y))
- #define Q_lt(x,y) ((x) < (y))
- #define Q_is_int(x) ((x & (Q_1 - Q_BIT)) == Q_0)
- #define Q_exp(a) (Q_BIT << (Q_SHIFT + a))
- #define Q_sprint(s,x) sprintf (s, "%d/%d", Q_p(x), Q_q(x))
-
- extern int Q_p (Q_type);
- extern int Q_q (Q_type);
- extern Q_type Q_times (Q_type, Q_type);
- extern Q_type Q_divide (Q_type, Q_type);
- extern Q_type Q_simplest_number (Q_type, Q_type);
- extern void Q_printf (Q_type);
- SHAR_EOF
- fi
- exit 0
- # End of shell archive
-